为什么这个NodeJS比本机C快2倍?

为了在工作中进行演示,我想比较NodeJS和C的性能。这是我写的:

Node.js(for.js):

var d = 0.0, start = new Date().getTime(); for (var i = 0; i > 1; } var end = new Date().getTime(); console.log(d); console.log(end - start); 

C(for.c)

 #include  #include  int main () { clock_t start = clock(); long d = 0.0; for (long i = 0; 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 ms。)在执行同样的操作时比原生C(198 ms。)快得多? Node.JS是否应用了GCC不能开箱即用的优化?

编辑:

根据评论中的建议,我运行了gcc -Wall -O2 for.c 结果改善为C需要29毫秒。 这就引出了一个问题,原生C设置如何不像Javascript编译器那样优化? 另外,-Wall和-02在做什么。 我真的很好奇这里发生的事情的细节。

这就引出了一个问题,原生C设置如何不像Javascript编译器那样优化?

由于C是静态编译和链接的,因此需要整个代码库的可能冗长的构建步骤(我曾经在一个花了将近一个小时进行完全优化构建的工作,否则只需要10分钟),以及非常危险的硬件 – 如果你不小心处理它会导致很多未定义行为冒险的级别语言,编译器的默认设置通常不会优化到smithereens,因为这是一个开发人员/调试版本,旨在通过更快的周转来帮助调试和提高工作效率。

因此,在C中,您可以在未优化但更快构建,更易于调试的开发人员/调试版本和非常优化,构建速度较慢,难以调试的生产/发布版本之间实现明显区分快,编译器的默认设置往往有利于前者。

使用像v8 / NodeJS这样的东西,你正在处理一个即时编译器(动态编译),它在运行时即时构建和优化必要的代码。 最重要的是,JS是一种更安全的语言,并且通常还设计用于安全性,不允许您使用硬件的原始位和字节。

因此,它不需要像C / C ++那样的本地静态编译语言的强大的发布/调试构建区别。 但是如果你真的想要的话,它也不会像你在C中那样把踏板踩到金属上。

很多人试图对来自其他语言的C / C ++进行基准测试,往往无法理解这种构建的区别以及编译器/链接器优化设置的重要性并使其混淆。 正如您所看到的,通过适当的设置,很难打败这些本机编译器和语言的性能,这些编译器和语言允许您编写真正的低级代码。

添加注册关键字有助于实现预期

 #include  #include  int main () { register long i, d; clock_t start = clock(); i = d = 0L; for (i = 0; i < 100000000L; 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); } 

并使用C编译器进行编译

  cc for.c -o for ./for ; node for.js 

回报

 2499999950000000 97 2499999950000000 222 

我还做了一些计算质数的测试,我发现Node.js的速度大约是C的两倍。

当你有一个非常简单的计数类型的循环时,-O2优化有时可以将输出转换为简单的公式,甚至不需要迭代循环。 请参阅Karl的博客了解一下。 如果你在例程中添加更复杂的东西,那么node.js可能会再次更快。 例如,我在您的示例程序中添加了一个devisor术语,并且c -O2优化不再能够将其转换为简单的公式并且node.js再次变得更快。

我仍然感到困惑的是,在简单的整数计算中,node.js如何比c更接近,但在我迄今为止所做的每一次测试中它都更快。 我还进行了一些我尚未发布的按位计算测试,但node.js仍然更快。