在Node中的进程之间发送数据是否昂贵/高效?

you*_*not 8 javascript node.js

Node允许您生成子进程并在它们之间发送数据.您可以使用它执行一些阻止代码,例如.

文档说"这些子节点仍然是V8的全新实例.假设每个新节点至少有30ms启动和10mb内存.也就是说,你不能创建数千个它们."

我想知道它是否有效,我是否应该担心一些限制?这是示例代码:

//index.js
var childProcess1 = childProcess.fork('./child1.js');

childProcess1.send(largeArray);

childProcess1.once('message', function(formattedData) {
  console.log(formattedData);
  return false;
});



//child1.js
process.on('message', function(data) {

  data = format(data); //do smth with data, then send it back to index.js

  try{
    process.send(data);
    return false;
  }
  catch(err){
    console.log(err);
    return false;
  }

});
Run Code Online (Sandbox Code Playgroud)

jos*_*736 31

文档告诉您启动新节点进程(相对)昂贵.fork()每次你需要做的工作都是不明智的.

相反,您应该维护一个长时间运行的工作进程池 - 就像一个线程池.在主进程中排队工作请求,并在空闲时将它们分派给下一个可用的工作程序.

这让我们对节点的IPC机制的性能概况提出了疑问.当您fork(),节点自动在子进程上设置特殊文件描述符.它使用它通过读取和写入行分隔的JSON在进程之间进行通信.基本上,当你process.send({ ... }),节点JSON.stringifys并将序列化的字符串写入fd.接收过程读取此数据,直到达到换行符,然后JSON.parse是它.

这必然意味着性能将高度依赖于您在进程之间发送的数据的大小.

我已经粗略地进行了一些测试,以便更好地了解这种性能.

首先,我向工作人员发送了一个N字节的消息,它立即响应了相同长度的消息.我在四核超线程i7上尝试了1到8个并发工作程序.

图形

我们可以看到,拥有至少2名工人对原始吞吐量有益,但超过2名基本上无关紧要.

接下来,我向工作人员发送了一条空消息,该消息立即响应了N个字节的消息.

图形

令人惊讶的是,这没有任何区别.

最后,我尝试向工作人员发送一个N字节的消息,该消息立即以空消息响应.

图形

有趣 - 性能不会随着较大的消息而迅速降低.

小贴士

  • 接收大邮件比发送邮件略贵. 为获得最佳吞吐量,主进程不应发送大于1 kB的消息,也不应接收大于128字节的消息.

  • 对于小消息,IPC开销约为0.02ms. 这个小到足以在现实世界中无关紧要.

重要的是要意识到消息的序列化是一个同步的阻塞调用; 如果开销太大,则在发送消息时将冻结整个节点进程.这意味着I/O将被饿死,您将无法处理任何其他事件(如传入的HTTP请求).那么通过节点IPC可以发送的最大数据量是多少?

图形

事情变得非常讨厌超过32 kB.(这些是按消息;双倍以获得往返开销.)

这个故事的寓意是你应该:

  • 如果输入大于32 kB,请找到让工作人员获取实际数据集的方法.如果您从数据库或其他网络位置提取数据,请在工作人员中执行请求.不要让主数据获取数据,然后尝试在消息中发送它.该消息应该只包含工作人员完成其工作的足够信息.想想功能参数之类的消息.

  • 如果输出大于32 kB,请找到让工作人员在消息之外传递结果的方法.写入磁盘或将套接字发送给worker,以便您可以直接从worker进程响应.