Dlaczego V8 w Node.JS jest szybszy niż w moim natywnym dodatku C++?

Dlaczego silnik Google V8 JavaScript w moim C++ addon działa znacznie wolniej niż w Node.JS?

Próbowałem napisać jakiś głupi prosty kod do generowania liczb pierwszych w JavaScript i uruchomiłem go w V8 za pomocą mojego C++ addon i bezpośrednio w Node.JS.

Byłem dość zszokowany, ponieważ obaj powinni używać tego samego silnika JavaScript i obaj wykonali ten sam kod (czas w milisekundach, mniej znaczy lepiej):

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

Oto źródło JavaScript moduł i źródło dodatku C++, który uruchamia ten sam kod JavaScript (i myślę, że problem nie w interopie, ponieważ pomiar czasu działa bezpośrednio w JS):

indeks.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;

rodzimy.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);
Author: holographic-principle, 2013-03-13

1 answers

W wersji C++ wszystkie zmienne zadeklarowane w źródle skryptu(result, primeNumberCounter, i, j, isPrime, start, end, time) są globalnymi , ponieważ zakres najwyższego poziomu skryptu to zakres globalny.

W celu optymalizacji kompilatora łatwo jest przydzielić zmienne lokalne do rejestrów maszynowych (lub szczelin rozlewanych na stosie) i śledzić ich typ. Z drugiej strony praca ze zmiennymi globalnymi wymaga stałego dostępu do pamięci i sprawdzania typu, ponieważ V8 nie wykonuje (obecnie) rejestru optymalizacja promocji.

Jeśli zawinie się źródło w od razu wywołaną różnicę funkcji, powinna zniknąć.

 44
Author: Vyacheslav Egorov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-13 22:58:20