为什么Node.JS中的V8比我的本地C ++插件更快?

为什么我的C ++插件中的Google V8 JavaScript引擎的工作速度比Node.JS慢得多?

我试着编写一些简单的代码来生成JavaScript中的素数,并通过C ++插件在V8中直接在Node.JS中运行它。

我感到非常震惊,因为它们都应该使用相同的JavaScript引擎,并且都执行相同的代码(时间以毫秒为单位)。

V8 in Node.JS: 495517 V8 in Node.JS C++ Addon: 623598 

这里是运行相同的JavaScript代码的JavaScript模块和C ++插件的源代码(我认为问题不在互操作中,因为时间的测量直接在JS中工作):

index.js

 var jsInNodeJsPrimeGeneratorBenchmark = require("./javascript.js"); var jsInNativePrimeGeneratorBenchmark = require("./native"); console.log("V8 in Node.JS: ", jsInNodeJsPrimeGeneratorBenchmark.primeGeneratorBenchmark()); console.log("V8 in Node.JS C++ Addon: ", jsInNativePrimeGeneratorBenchmark.primeGeneratorBenchmark()); 

javascript.js

 function primeGeneratorBenchmark() { var result, primeNumberCounter, i, j, isPrime, start, end; i = 3; primeNumberCounter = 1; start = Date.now(); while (primeNumberCounter < 100000) { isPrime = true; for (j = 2; j < i; j++) { if (i % j === 0) { isPrime = false; break; } } if (isPrime) { result = i; primeNumberCounter++; } i++; } end = Date.now(); return end - start; } exports.primeGeneratorBenchmark = primeGeneratorBenchmark; 

native.cpp

 #include <node.h> v8::Handle<v8::Value> primeGeneratorBenchmark(const v8::Arguments &arguments); void registerModule(v8::Handle<v8::Object> target); v8::Handle<v8::Value> primeGeneratorBenchmark(const v8::Arguments &arguments) { v8::HandleScope handleScope; v8::Local<v8::Context> context = arguments.Holder()->CreationContext(); v8::Context::Scope scope(context); const char *sourceStringC = "var result, primeNumberCounter, i, j, isPrime, start, end, time;\n" "i = 3;\n" "primeNumberCounter = 1;\n" "start = Date.now();\n" "while (primeNumberCounter < 100000) {\n" " isPrime = true;\n" " for (j = 2; j < i; j++) {\n" " if (i % j === 0) {\n" " isPrime = false;\n" " break;\n" " }\n" " }\n" " if (isPrime) {\n" " result = i;\n" " primeNumberCounter++;\n" " }\n" " i++;\n" "}\n" "end = Date.now();\n" "time = end - start;\n"; v8::Local<v8::String> sourceStringV8 = v8::String::New(sourceStringC); v8::Local<v8::Script> script = v8::Script::Compile(sourceStringV8); script->Run(); v8::Local<v8::Value> timeResult = v8::Context::GetCurrent()->Global()->Get(v8::String::New("time")); return handleScope.Close(timeResult); } void registerModule(v8::Handle<v8::Object> target) { target->Set(v8::String::NewSymbol("primeGeneratorBenchmark"), v8::FunctionTemplate::New(primeGeneratorBenchmark)->GetFunction()); } NODE_MODULE(native, registerModule); 

在C ++版本中,在脚本源( resultprimeNumberCounterijisPrimestart ,end, time )中声明的所有variables都是全局variables,因为脚本的顶级范围是全局范围。

为了优化编译器,很容易将局部variables分配到机器寄存器(或堆栈上的溢出槽)并跟踪它们的types。 另一方面,使用全局variables需要持续的内存访问和types检查,因为V8没有(当前)执行寄存器提升优化。

如果你把源代码包装成一个立即调用的函数差异就应该消失。