nodejs – 我发现multithreading或使用多个进程比单个进程慢。 为什么?

我有一个CPU密集型任务(循环通过一些数据和评估结果)。 我想利用这些多核心,但我的performance一直比使用单个核心更糟糕。

我试过了:

  • 在不同的端口上创build多个进程,并将任务发送到这些进程
  • 使用webworker-threads来使用线程池在不同线程中运行任务

通过计算我可以完成的迭代总数并除以我在这个问题上花费的时间来衡量结果。 当使用单核时,我的结果明显更好。

一些兴趣点:

  • 我可以确定何时使用一个内核,何时通过任务pipe理器使用多个内核。 我正在使用预期的内核数量。
  • 我有很多的内存
  • 我已经试过在2或3个内核上运行
  • 我添加了nextTicks,在这种情况下似乎没有任何影响
  • 每个任务都需要几秒钟的时间,所以我不觉得自己失去了很多开销

有什么想法在这里发生了什么?

线程更新:我怀疑webworker线程中的错误跳过表示现在,我认为这个问题可能与我的线程循环。 我正在做的是创build一个线程,然后试图连续运行它们,但在它们之间来回发送数据。 即使这两个线程正在使用CPU,只有线程0返回值。 我的假设是散发出来的,通常最终会把信息传递给闲置时间最长的线程,但似乎并非如此。 我的设置看起来像这样

在threadtask.js中

thread.on('init', function() { thread.emit('ready'); thread.on('start', function(data) { console.log("THREAD " + thread.id + ": execute task"); //... console.log("THREAD " + thread.id + ": emit result"); thread.emit('result', otherData)); }); }); 

main.js

 var tp = Threads.createPool(NUM_THREADS); tp.load(threadtaskjsFilePath); var readyCount = 0; tp.on('ready', function() { readyCount++; if(readyCount == tp.totalThreads()) { console.log('MAIN: Sending first start event'); tp.all.emit('start', JSON.stringify(data)); } }); tp.on('result', function(eresult) { var result = JSON.parse(eresult); console.log('MAIN: result from thread ' + result.threadId); //... console.log('MAIN: emit start' + result.threadId); tp.any.emit('start' + result.threadId, data); }); tp.all.emit("init", JSON.stringify(data2)); 

输出到这个灾难

 MAIN: Sending first start event THREAD 0: execute task THREAD 1: execute task THREAD 1: emit result MAIN: result from thread 1 THREAD 0: emit result THREAD 0: execute task THREAD 0: emit result MAIN: result from thread 0 MAIN: result from thread 0 THREAD 0: execute task THREAD 0: emit result THREAD 0: execute task THREAD 0: emit result MAIN: result from thread 0 MAIN: result from thread 0 THREAD 0: execute task THREAD 0: emit result THREAD 0: execute task THREAD 0: emit result MAIN: result from thread 0 MAIN: result from thread 0 

我也尝试了另外一种方法,在那里我会发射所有,但是然后让每个线程听一条消息,只有它可以回答。 例如,thread.on('start'+ thread.id,function(){…})。 这是行不通的,因为在执行tp.all.emit('start'+ result.threadId,…)的结果时,消息不会被拾取。

 MAIN: Sending first start event THREAD 0: execute task THREAD 1: execute task THREAD 1: emit result THREAD 0: emit result 

之后没有更多的事情发生。

更新多个快递服务器:我得到了改进,但比预期的要小

我重新考虑这个解决scheme,并有更多的运气。 我想我原来的测量可能是有缺陷的。 新的结果:

  • 单进程:3.3次/秒
  • 主进程+2个服务器:4.2次/秒
  • 主进程+3台服务器:每秒4.9次

我发现有一点奇怪的是,我没有看到2台服务器的每秒6次迭代和3次的9次。我知道networking有一些损失,但是如果我将任务时间增加到足够高,networking损失应该是相当小的,我会想。

您不应该推动您的Node.js进程运行多个线程来提高性能。 在一个四核处理器上运行,有一个express处理一般请求和三个express处理CPU密集请求的express进程可能是最有效的设置,这就是为什么我build议你试着devise你的express进程来推迟使用networking工作者,只是阻止,直到他们产生的结果。 这将使您得到一个单一的线程,按devise运行一个单一的进程,最有可能产生最好的结果。

我不知道Web工作包如何处理同步,影响发生在c空间等等的Node.js的I / O线程池的复杂性,但是我相信您通常会想要引入Web工作者来能够同时pipe理更多阻塞任务,而不会严重影响不需要线程和系统I / O的其他请求,否则可以方便地进行响应。 这并不一定意味着应用这将会为正在执行的特定任务带来改进的性能。 如果使用4个执行I / O的线程运行4个进程,则可能会locking浪费时间在应用程序空间之外的线程上下文之间不断切换。