为什么在 v8 中运行嵌入在 c++ 中的非常简单的脚本会占用内存?
Why does running a very simple script in v8, embedded in c++, use up memory?
我在V8中运行一个非常简单的javascript脚本,嵌入在C++程序中。脚本只是一个数字文字:"12"。但是,当我在循环中多次运行此脚本时,我的应用程序将在 20-30 秒后消耗几 GB 的内存。我使用的是V8 7.5.160,它是在Windows 10和Visual Studio 2017下构建的。
我运行这段代码的原因是了解从C++执行 javascript 时的函数调用开销。我正在研究使用 V8 作为应用程序的脚本引擎,该应用程序将以非常高的速率调用许多小脚本。但是内存使用让我担心。
我一直在寻找手动触发垃圾收集器的方法。但据我了解,这应该是不必要的(而且我找不到该怎么做)。 但我更感兴趣的是我是否可以首先阻止这种内存使用。
我使用了 V8 嵌入文档 (hello-world.cc) 中的示例代码,使用不同的脚本,在循环中运行脚本并计时执行调用所需的时间:
// V8 setup code, unchanged from the V8 embedding hello-world.cc.
// My script:
v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, "12", v8::NewStringType::kNormal).ToLocalChecked();
// Compile script:
v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();
// Then this code in two nested loops, where the inner loop times the time it takes.
// The outer loop runs 20 times. The inner loop runs 100.000.000 times.
// Inside the inner loop there is only this line of code:
script->Run(context).ToLocalChecked();
我期望这段代码不会导致如此高的内存使用率。或者至少,我希望垃圾回收器能够保持较低的内存使用率。
如果能深入了解导致此脚本内存使用的原因以及防止这种情况发生的方法,我将不胜感激。
已解决:
jmrk提供的解决方案(谢谢!)解决了我的问题。 我将运行 100.000.000 次的内部循环分成两个循环;具有 100.000 次迭代的外部循环和具有 1000 次迭代的内部循环。在这个内部循环之前,我确实v8::HandleScope temp_scope(isolate);
,现在没有更极端的内存使用。应用程序现在保持在 2.3MB 的使用量。 每次脚本运行的总时间也没有增加。相反,它从85ns略微下降到82ns。
尝试在调用周围使用短暂的HandleScope
:
for (int i = 0; i < 20; i++) {
/* Record start time */
for (int j = 0; j < 1000; j++) {
v8::HandleScope temp_scope(isolate);
for (int k = 0; k < 100000; k++) {
script->Run(context).ToLocalChecked();
}
}
/* Record end time */
}
背景是.ToLocalChecked()
创建了一个新的v8::Local
,只要当前HandleScope
存在,其内容(=脚本调用的结果)就会保持活动状态。因此,通过在一个HandleScope
内为许多新对象创建许多新句柄,您可以有效地禁用垃圾回收。
权衡是HandleScope
创建/销毁具有(小)性能成本,但经常重新创建它们会使更多内存符合垃圾回收条件(并且还会稍微加快垃圾回收本身的速度)。根据经验,我的目标是每HandleScope
大约 1,000 到 1,000,000 个句柄。
- 将字符串存储在c++中的稳定内存中
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- Win32编译器选项和内存分配
- 当vector是tje全局变量时,c++中vector的内存管理
- 带内存和隔离功能的SQLite
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 迭代时从向量和内存中删除对象
- 如何通过cpp程序运行shell脚本
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 为什么示例代码访问IUnknown中已删除的内存
- 如何在C++类内存结构中创建"spacer"?
- 从构造函数抛出异常时如何克服内存泄漏
- malloc() 可能出现内存泄漏
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 如何在 ubuntu 上的 php 脚本中获取程序(c,c++,java,python,php)的执行时间和内存使用量?
- 为什么在 v8 中运行嵌入在 c++ 中的非常简单的脚本会占用内存?
- 在程序内存中执行BATCH脚本
- 调用一个外部C++函数,Memory Leaks:将在完成Python脚本后清理所有分配的内存