Node.js集群 - 最佳工作进程数量

3

我有4个核心,根据这个例子运行了这段代码:

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

var id = 0;
if (cluster.isWorker) {
    id = cluster.worker.id;
}

var iterations = 1000000000;
console.time('Function #' + id);
for (var i = 0; i < iterations; i++) {
    var test = 0;
}
console.timeEnd('Function #' + id);

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }
}

使用4个fork(上面的代码),我得到了以下结果:
第1函数:1698.801毫秒 第2函数:3282.679毫秒 第3函数:3425.090毫秒 第4函数:3290.384毫秒 第5函数:3424.922毫秒
使用3个fork,我得到了以下结果:
第1函数:1695.155毫秒 第2函数:1822.867毫秒 第3函数:2444.156毫秒 第4函数:2606.680毫秒
使用2个fork,我得到了以下结果:
第1函数:1684.929毫秒 第2函数:1682.897毫秒 第3函数:1686.123毫秒
我不明白这些结果。难道不是每个核心一个fork(即1个fork/核心)才是最佳选择吗?在这里,我发现4个fork并不比2个fork更好。
1个回答

7

我的猜测是你的硬件实际只有2个 物理 核心。但是,由于 超线程 (HT),操作系统将显示存在4个 (逻辑) 核心。

你代码中的工作线程会完全占用一个 (物理) 核心,这是 HT 处理不好的事情,因此当所有4个逻辑核心都很忙碌时,性能会比只让2个物理核心保持繁忙时更差。

我的硬件(四核心,因此有4个实体和8个逻辑核心)显示了相同的模式:

  • 8 workers:

    Function #5: 926ms
    Function #3: 916ms
    Function #1: 928ms
    Function #4: 895ms
    Function #7: 934ms
    Function #6: 905ms
    Function #8: 928ms
    Function #2: 928ms
    
  • 4 workers:

    Function #3: 467ms
    Function #2: 467ms
    Function #1: 473ms
    Function #4: 472ms
    

话虽如此,如果您的工作者是I/O绑定的(大多数Node应用程序都是如此),那么按照硬件逻辑核心数量制定与工作者数量相等的规则仍然是有意义的。

如果您真的想执行大量阻塞的计算,请将每个工作者计算为一个物理核心。


感谢提供的信息。那么对于Node.js,另一半的核心只用于异步代码?这是否需要集群,或者这意味着Node.js仅使用一个执行线程,但同时也使用其他并行线程(~核心?)来处理异步代码?此外,由于我正在开发游戏,它主要是CPU绑定的。但是我在github上看到了一些在主循环中的setTimeout(updateClients, 0);,因为“异步更新可以提高性能”。他们是正确的吗? - zbeyens
1
Node本身不会安排任何事情,这取决于操作系统(以及CPU本身)。如果您有CPU绑定的代码,则cluster可以帮助您,因为它允许您在单独的进程中运行CPU密集型代码,该进程可以由操作系统调度到应用程序的不同代码作为“主”部分。如果您将I/O绑定和CPU绑定的核心混合在同一个进程中,则使用setTimeout()技巧很有用。 - robertklep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接