【发布时间】:2015-02-10 12:49:30
【问题描述】:
为了在工作中进行演示,我想将 NodeJS 的性能与 C 进行比较。这是我写的:
Node.js (for.js):
var d = 0.0,
start = new Date().getTime();
for (var i = 0; i < 100000000; i++)
{
d += i >> 1;
}
var end = new Date().getTime();
console.log(d);
console.log(end - start);
C (for.c)
#include <stdio.h>
#include <time.h>
int main () {
clock_t start = clock();
long d = 0.0;
for (long i = 0; i < 100000000; i++)
{
d += i >> 1;
}
clock_t end = clock();
clock_t elapsed = (end - start) / (CLOCKS_PER_SEC / 1000);
printf("%ld\n", d);
printf("%lu\n", elapsed);
}
我使用 GCC 编译了我的 for.c 并运行它:
gcc for.c
./a.out
结果:
2499999950000000
198
然后我在 NodeJS 中试了一下:
node for.js
结果:
2499999950000000
116
经过多次运行,我发现无论如何都是如此。如果我将 for.c 切换为在循环中使用 double 而不是 long,那么 C 花费的时间会更长!
不是想发起一场激烈的战争,但为什么 Node.JS(116 毫秒)在执行相同操作时比原生 C(198 毫秒)快这么多? Node.JS 是否应用了 GCC 没有开箱即用的优化?
编辑:
根据 cmets 的建议,我运行了 gcc -Wall -O2 for.c。结果提高到 C 需要 29 毫秒。这就引出了一个问题,为什么原生 C 设置没有像 Javascript 编译器那样优化?另外,-Wall 和 -02 在做什么。我真的很好奇这里发生了什么。
【问题讨论】:
-
尝试使用
gcc -Wall -O2 for.c编译并再次进行基准测试。使用gcc(或clang)而不通过任何显式优化标志进行基准测试是没有用的! -
您在 Node.js 中测量 wall 时间,在 C 中测量 CPU 时间。
-
再次测量编译:
gcc -march=native -O2 for.c(我的编译器标志为 260,我的编译器标志为 98!即使只是-O1也将运行时间减少到一半以下。) -
嗯,v8 引擎也不是解释器,它会编译代码(并在可能的情况下动态优化它)。
-
简短的回答是,当您不指定任何优化时,gcc 不会进行 any 优化。它只是尽可能快地生成代码,不管它运行得有多慢。编译 C(和 C++)往往很慢,以至于对于大多数开发来说,大多数人只想让一些东西尽快运行,不管运行速度有多慢。只有当代码至少接近完成时,它们才会打开优化器并忍受较慢的编译时间。
标签: c node.js performance optimization