Javascript 是节点';“子进程”;“很多”;更慢的?

Javascript 是节点';“子进程”;“很多”;更慢的?,javascript,node.js,child-process,Javascript,Node.js,Child Process,考虑以下近似pi的代码: // filename: pi.js function approx_pi(from, to) { var pi = 0; var dx = 0.0000000005; for(var x = from; x < to; x += dx) { pi += 4 / (1 + x * x); } return pi * dx; } var min = Infinity; var max = -1; var av

考虑以下近似pi的代码:

// filename: pi.js
function approx_pi(from, to) {
    var pi = 0;
    var dx = 0.0000000005;
    for(var x = from; x < to; x += dx) {
        pi += 4 / (1 + x * x);
    }
    return pi * dx;
}

var min = Infinity;
var max = -1;
var avg = 0;

for(var itr = 0; itr < 10; ++itr) {
    var start = process.hrtime();
    var pi = approx_pi(0, 1);
    var diff = process.hrtime(start);

    var duration = diff[0] + diff[1] * 1e-9;

    min = (duration <= min) ? duration : min;
    max = (duration >= max) ? duration : max;
    avg += duration;
}

avg /= 10;

min = min.toFixed(3);
max = max.toFixed(3);
avg = avg.toFixed(3);

console.log("Time: min = %ss, max = %ss , avg = %ss", min, max, avg);
运行
节点children.js 1
(这是预期的)也会产生类似的结果

当不止一个孩子被叉子叉着的时候,事情开始变得奇怪(至少我自己是这么想的)。以下是运行
节点children.js 2
后的输出:

Time: min = 29.824s, max = 41.050s , avg = 35.136s
Time: min = 30.036s, max = 40.791s , avg = 35.246s
每个孩子比单个版本至少多花费14秒。使用
node children.js 4
运行4个子节点时,情况变得更糟,每一个子节点都需要大约37秒才能完成:

Time: min = 55.878s, max = 68.047s , avg = 58.845s
Time: min = 52.760s, max = 69.168s , avg = 58.880s
Time: min = 57.151s, max = 69.113s , avg = 58.956s
Time: min = 50.790s, max = 70.344s , avg = 59.546s
这些测试运行在一台具有2.30GHz内核i5 2410M CPU(操作系统可以看到4个内核)和4GB RAM的机器上,这两台机器都运行:运行node v4.2.3的Windows 7和运行node v5.4.1的Ubuntu14.04。每个操作系统都显示每个子系统都在自己的内核上运行,并且每个子系统都有相同数量的分配内存(大约9MB)

根据节点文档:“每个进程都有自己的内存,有自己的V8实例”。因此,我们期望每个孩子都能像单个过程一样表现出色


我的期望是否被误导了?这是预期的行为还是正在发生的事情?

您在一个CPU上并行运行4个进程,然后测量实际时间而不是CPU时间。当然,每个过程都需要更长的时间。。。您不能在有限数量的内核上运行无限数量的进程,并且期望运行时间与在多个内核上运行单个进程相同。(如果有人知道如何做到这一点,那么网络安全就完蛋了。)


您可能期望在两个内核上运行的两个进程与单个进程(必须在单个内核上运行)同时运行,但实际情况往往与理论不太一样。很可能您的两个进程实际上在同一个核心上共享时间。没有简单的方法可以保证每个流程都有自己的核心,因为这些细节几乎总是从您的控制中抽象出来。

您的测试应该至少循环10次,然后报告最小、最大和平均时间。这给了V8编译代码的时间(第一次运行总是最慢的)。另外,Date.now()不是很精确(因此它往往会高估时间)。@JDB我平均了10次迭代,正如您指出的,并使用
process.hrtime
而不是
Date.now
。不过数据差别不大。我在我的机器上禁用了超线程,这样操作系统可以看到的两个内核实际上是两个内核,而不是同一个内核上的两个线程。然后我运行了
node children.js 1
node children.js 2
,这次的差异大约是+10秒(比使用超线程时稍微小一点,即+14秒),但仍然很大!我尝试了同样的任务用C++使用MPI,差值大约+3.3s!你认为JS中的额外+6 7s仅仅是因为JS上的C++速度吗?你仍然不能保证每个进程都运行在一个单独的内核上。这是最关键的。。。它们是在单独的内核上运行(真正并行)还是共享一个内核(降低每个内核的速度)?单个子进程与其父进程同时运行的事实表明,子进程并不较慢。速度差与C++似乎不相关的我…我猜想C++在运行时速度更快,因为它在使用JIT编译器时被编译成本地字节码,所以比原始数字更快的速度更好。根据OS任务管理器,它们在单独的内核上运行。当我关闭其中一个进程时,一个核心的利用率下降,而另一个保持在100%。但问题是,当一个子进程运行时,它自身需要一个完整的内核,操作系统进程和父进程共享另一个内核。当两个子系统同时在两个内核上运行时,它们不可能自己拥有所有内核,而是与其他操作系统进程共享。这就解释了为什么它们需要更长的时间,但差异的大小正是困扰我的原因!我认为这是一个很好的研究课题,但我不认为你的测试真的证明了两者之间存在差异或差异是什么。与节点相比,C++是极其优化的,精益代码是这一点,这也是游戏程序员仍然喜欢它的原因。我认为在声明节点子进程实际上需要更长的时间之前,您需要做更多的测试。我想是这样的。我认为这些测试需要在一个更可控的环境中运行,以便能够从中推断出任何东西。谢谢你的帮助!
Time: min = 17.323s, max = 21.465s , avg = 19.979s
Time: min = 29.824s, max = 41.050s , avg = 35.136s
Time: min = 30.036s, max = 40.791s , avg = 35.246s
Time: min = 55.878s, max = 68.047s , avg = 58.845s
Time: min = 52.760s, max = 69.168s , avg = 58.880s
Time: min = 57.151s, max = 69.113s , avg = 58.956s
Time: min = 50.790s, max = 70.344s , avg = 59.546s