2016-11-26 145 views
1

我正在使用Node.js产生100个以上的子进程,可能甚至是1000.我关心的是父进程可能会成为某种瓶颈如果所有的子进程的stdout/stderr必须通过父进程才能在某处登录。从父进程派生/产生许多node.js进程的最高性能方式

所以我的假设是,为了达到最高的性能/吞吐量,我们应在父进程忽略标准输出/标准错误,就像这样:

const cp = require('child_process'); 

items.forEach(function(exec){ 

    const n = cp.spawn('node', [exec], { 
     stdio: ['ignore','ignore','ignore','ipc'] 
    }); 

}); 

我的问题是,如何在性能损失的钱它以这种方式使用管道:

// (100+ items to iterate over) 

items.forEach(function(exec){ 

    const n = cp.spawn('node', [exec], { 
     stdio: ['ignore','pipe','pipe','ipc'] 
    }); 

}); 

这样,stdout和stderr被传送到父进程?我假设的性能损失可能是激烈的,特别是如果我们处理标准输出/标准错误在父进程中,像这样:

 // (100+ items to iterate over) 

    items.forEach(function(exec){ 

     const n = cp.spawn('node', [exec], { 
      stdio: ['ignore','pipe','pipe','ipc'] 
     }); 

     n.stdout.setEncoding('utf8'); 
     n.stderr.setEncoding('utf8'); 

     n.stdout.on('data', function(d){ 
      // do something with the data 
     }); 

     n.stderr.on('data', function(d){ 
      // do something with the data 
     }); 

    }); 

我假设

  1. 我认为,如果我们用“忽略”的标准输出和在父进程中stderr, 这比管道标准输出/标准错误到父进程更高性能。
  2. 我认为,如果我们选择一个文件流的标准输出/标准错误喜欢这样

    stdio: ['ignore', fs.openSync('/some/file.log'), fs.openSync('/some/file.log'),'ipc']

,这几乎是用“忽略”的标准输出/标准错误(应该送作为高性能stdout/stderr到/ dev/null)

这些假设是否正确?关于stdout/stderr,如果我想将stdout/stderr记录到某处(而不是/ dev/null),如何实现最高性能?

注:这是一个库,所以stdout/stderr的数量可能会有很大的不同。此外,最有可能很少分叉更多的进程比核心,最多同时运行约15个进程。

+0

如果源代码出现问题,部分答案在这里:https://github.com/nodejs/node/blob/master/lib/child_process.js –

+0

并在这里:https://github.com/ nodejs/node/blob/master/lib/internal/child_process.js –

+0

你的程序库需要分叉多少子进程? – robertklep

回答

1

这些假设是否正确?

我该如何实现最高性能?

测试它。这就是你如何实现最高性能。测试您将在生产中使用的相同类型的系统,具有相同数量的CPU和类似的磁盘(SSD或HDD)。

我假设你的担心是,如果父母读得不够快,孩子可能会被阻止。这是一个潜在的问题,取决于管道的缓冲区大小以及流经它的数据量。但是,如果替代方法是让每个子进程独立写入磁盘,则可能会更好,相同或更糟。我们并不知道一大堆原因,首先是我们不知道您有多少内核,您的进程生成数据的速度以及您写入的I/O子系统。

如果您有一个SSD,则可以每秒写入500 MB。这太好了,但如果SSD的容量是512 GB,那么它只会在满满之前持续16分钟!在任何人都知道什么是最有效的方法之前,你需要缩小问题空间的范围。

如果您的目标仅仅是尽可能少的系统利用率从机器上获取记录的数据,那么最好的办法就是直接将日志消息写入网络。

+0

那么,这将运行在各种系统上,因为这是针对图书馆的。因此,或许我们可以在某种程度上假定除了所讨论的变量之外“所有事情都是平等的” - 这实际上是否将一个孩子的stdout/stderr传递给父级,而不是将它传递给/ dev/null或一个文件,我只是不太清楚计算机是否可以确定的方式。 –

+0

我可以在我的系统上测试它,但它不会像下一个在它们上运行它的人那样相同,我只想知道平均情况/所有其他东西是相等/固定的情况 –

+0

@AlexanderMills你应该说你正在写一个图书馆!这非常重要,你根本没有提及它!告诉我们更多关于它的信息......仅供内部使用一个项目,内部使用于您工作的公司中的许多项目的内部使用,还是供您可能永远不会互动的人员使用?如果是后者,如果不能测试哪种方式更好,则可以将其配置为可配置。 –

1

您有以下选择:

  • 你可以有子进程完全忽略标准输出/标准错误,并以任何其他方式自行做记录(记录一个到一个文件,系统日志... )

  • 如果您记录父进程的输出,则可以分别将stdout/stderr设置为process.stdoutprocess.stderr。这意味着孩子的输出将与主要过程相同。没有任何东西会流过主流程

  • 您可以直接设置文件描述符。这意味着子进程的输出将在给定的文件中执行,而不通过父进程

  • 但是,如果您没有对子进程的任何控制权,并且您需要以某种方式对日志执行某些操作(过滤它们,在关联的子进程中加上前缀等),那么你可能需要经过父进程。

由于我们不知道您所谈论的日志量,我们不知道这是关键还是过早优化。 Node.js是异步的,我不希望你的父进程成为瓶颈,除非它真的很忙,并且你有很多日志。

+0

我确实在一定程度上可以控制子进程 - 但是日志记录的容量可能会有很大差异,具体取决于用户,并且在某些情况下,我假定可以记录很多stdout/stderr –

+0

“很多”是多少? – jcaron

+0

我不知道,但如果你有100个进程都向单个进程发送大量的stdout/stderr,并且该进程必须处理它,我认为它会比如果这100个进程各自独立发送它们的标准输出/ stderr来分离文件 –