为什么V8在Node.JS中比我的本地c++插件快
Why V8 in Node.JS is faster than in my native C++ addon?
为什么谷歌的V8 JavaScript引擎在我的c++插件工作明显慢于在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++版本中,脚本源中声明的所有变量(result
, primeNumberCounter
, i
, j
, isPrime
, start
, end, time
)都是global,因为脚本的顶级作用域是全局作用域。
为了优化编译器,很容易将局部变量分配到机器寄存器(或溢出堆栈槽)并跟踪它们的类型。另一方面,使用全局变量需要恒定的内存访问和类型检查,因为V8(目前)没有执行寄存器提升优化。
如果将源代码包装成一个立即调用的函数,那么差异就会消失。
相关文章:
- 从C++本机插件更新Vector3数组
- 使用CMake创建QML插件
- 停止cmake target_link_libraries将插件中静态库的两个对象文件链接到静态库本身
- 如何创建从Maya(或类似程序)到虚幻引擎的自定义数据导出插件
- clang 插件:在编译过程中修改 AST
- 实现动态插件管理器
- 我想通过带有C++和Python的插件创建一个可扩展的应用程序
- Agora.io 虚幻引擎插件构建错误
- 使用带有C++对象和标准库容器的插件系统
- 运行命令 "rosbag play example.bag" 时出错。找不到与插件 rosbag/NoEncryptor 对应的库
- 编译 llvm 插件时出现问题:llvm/Config/llvm-config.h:没有这样的文件或目录
- 通过 Gazebo 世界插件将静态对象附加到机器人链接
- 如何为模块化应用程序实现C++插件系统
- 'string'文件在带有C++文件的iOS插件上找不到
- 在 Android 上安装 GStreamer 插件
- 如何使用MSVC 2019创建和使用Qt 5.14.0自定义小工具插件
- 如何在 Windows 操作系统中在 geany 中安装插件
- 节点插件 API 将数组作为函数参数传递
- OpenVINO - 推理库插件 libMKLDNNPlugin.so 无法解析依赖关系
- 通过 Flutter 从C++插件访问资产