[英]Why V8 in Node.JS is faster than in my native C++ addon?
為什么我的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 ++插件的源代碼(我認為問題不在interop中,因為測量時間直接在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 ++版本中,腳本源( result
, primeNumberCounter
, i
, j
, isPrime
, start
,end, time
)中聲明的所有變量都是全局變量,因為腳本的頂級作用域是全局作用域。
為了優化編譯器,很容易將局部變量分配到機器寄存器(或堆棧中的溢出槽)並跟蹤它們的類型。 另一方面,使用全局變量需要恆定的內存訪問和類型檢查,因為V8(當前)不執行寄存器升級優化。
如果將源包裝成一個立即調用的函數,則應該消失。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.