首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >V8隔离映射内存泄漏

V8隔离映射内存泄漏
EN

Stack Overflow用户
提问于 2019-12-31 13:26:48
回答 1查看 288关注 0票数 1

需要V8开发人员。

我注意到下面的代码泄漏了映射的内存(mmap,munmap),具体而言,cat /proc/<pid>/maps中映射区域的数量不断增长,并且很快就达到了系统限制(/proc/sys/vm/max_map_count)。

代码语言:javascript
运行
复制
void f() {
  auto platform = v8::platform::CreateDefaultPlatform();
  v8::Isolate::CreateParams create_params;

  create_params.array_buffer_allocator =
    v8::ArrayBuffer::Allocator::NewDefaultAllocator();

  v8::V8::InitializePlatform(platform);
  v8::V8::Initialize();

  for (;;) {
    std::shared_ptr<v8::Isolate> isolate(v8::Isolate::New(create_params), [](v8::Isolate* i){ i->Dispose(); });
  }

  v8::V8::Dispose();
  v8::V8::ShutdownPlatform();

  delete platform;
  delete create_params.array_buffer_allocator;
}

我对platform-linux.cc文件做了一些处理,发现UncommitRegion调用只是用PROT_NONE映射区域,但没有释放它。也许这与那个问题有某种联系。

我们在程序执行过程中重新创建隔离有几个原因。

首先,在GC方面,创建新的隔离和抛弃旧的隔离是更可预测的。基本上,我发现

代码语言:javascript
运行
复制
auto remoteOldIsolate = std::async(
    std::launch::async,
    [](decltype(this->_isolate) isolateToRemove) { isolateToRemove->Dispose(); },
    this->_isolate
);

this->_isolate = v8::Isolate::New(cce::Isolate::_createParams);

// 

比调用LowMemoryNotification更可预测和更快。因此,我们使用GetHeapStatistics监视内存消耗,并在达到极限时重新创建隔离。事实证明,我们不能将GC活动视为代码执行的一部分,这会导致糟糕的用户体验。

第二个原因是,让每个代码隔离允许并行运行多个代码,否则v8::Locker将阻塞该特定隔离的第二个代码。

在这个阶段,我没有选择,我将重写应用程序,以便在每个code..of过程中都有一个隔离和持久上下文池,这样,code#1可能会通过执行许多分配来影响code#2,并且GC将在没有分配的code2上运行,但至少不会泄漏。

PS。我已经提到过,我们使用GetHeapStatistics来监视内存。我想澄清一下这部分。

在我们的例子中,当GC在代码执行期间工作时,这是一个很大的问题。每个代码都有执行超时(100到500 has )。在代码执行期间让GC活动锁定代码,有时我们只为分配操作设置超时。GC回调不能给您足够的准确性,所以我们不能依赖它们。

实际上,我们指定了--max-old-space-size=32000 (32 we )。那样的话,GC就不想运行了,因为它应该看到存在大量的内存。使用GetHeapStatistics (以及上面提到的隔离娱乐),我们有手动内存监视。

PPS。我还提到,代码之间的共享隔离可能会影响用户。假设你有user#1user#2。他们每个人都有自己的代码,两者都是不相关的。code#1有一个具有大量内存分配的循环,code#2只是一个赋值操作。GC有可能在code#2期间运行,user#2将收到超时。

EN

回答 1

Stack Overflow用户

发布于 2020-01-03 14:51:42

需要V8开发人员。

请在crbug.com/v8/new上注册一个bug。请注意,这个问题可能被认为是低优先级的;我们通常假设每个流程的分离数量仍然相当少(即,不是数千个或数百个)。

有一群分离物

是的,那可能就是该走的路了。特别是,正如您已经写过的,如果要并行执行脚本,则每个线程都需要一个隔离器。

通过这种方式,code#1可能会通过执行许多分配来影响code#2,并且GC将在根本没有分配的code2上运行。

不,那不可能发生。只有分配触发GC活动。无分配代码将花费零时间进行GC。此外(正如我们在前面的问题中所讨论的),GC活动被分成许多微小的(通常为亚毫秒)的步骤(这些步骤反过来由分配触发),因此,特别是短时间运行的代码不会遇到巨大的GC暂停。

有时我们只为外派操作设置超时。

这听起来令人惊讶,而且听起来与GC无关;我敢打赌还有别的事情要发生,但我不知道会发生什么。你有复制品吗?

我们指定--最大旧空间大小=32000(32 we )。那样的话,GC就不想运行了,因为它应该看到存在大量的内存。使用GetHeapStatistics (以及上面提到的隔离娱乐),我们有手动内存监视。

你试过什么都不做吗?V8的GC在默认情况下是非常精细的调整,我认为这样做会导致更多的问题,而不是解决问题。当然,您可以尝试任何您喜欢的行为;但是,如果结果行为不是您所期望的,那么我的第一个建议就是让V8做它的事情,并且只有当您发现默认行为某种程度上不能令人满意时,才会进行干预。

code#1有一个具有大量内存分配的循环,code#2只是一个赋值操作。GC有可能在code#2期间运行,user#2将收到超时。

再说一次:没有。不分配的代码不会被GC中断。而且同一隔离器中的几个函数永远不能并行运行;只有一个线程可以同时在一个隔离器中活动。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59544711

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档