简体   繁体   中英

Why V8 in Node.JS is faster than in my native C++ addon?

Why Google's V8 JavaScript engine in my C++ addon works significantly slower than in Node.JS?

I've tried to write some stupidly simple code for generating prime numbers in the JavaScript and ran it in V8 via my C++ addon and directly in Node.JS.

I was quite shocked, because both should be using the same JavaScript engine and both have executed the same code (time in milliseconds, less is better):

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

Here is the source of JavaScript module and source of C++ addon that runs same JavaScript code (and I think problem not in the interop, because measuring of time works directly in 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);

In the C++ version all variables declared in the script source ( result , primeNumberCounter , i , j , isPrime , start , end, time ) are global because script's top level scope is global scope.

For optimizing compiler it is easy to allocate local variables into machine registers (or spill slots on stack) and keep track of their type. Working with global variables on the other hand requires constant memory accesses and type checks because V8 does not (currently) perform a register promotion optimization.

If you wrap the source into an immediately called function difference should go away.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM