需要V8开发人员。
我注意到下面的代码泄漏了映射的内存(mmap,munmap),具体而言,cat /proc/<pid>/maps中映射区域的数量不断增长,并且很快就达到了系统限制(/proc/sys/vm/max_map_count)。
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方面,创建新的隔离和抛弃旧的隔离是更可预测的。基本上,我发现
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#1和user#2。他们每个人都有自己的代码,两者都是不相关的。code#1有一个具有大量内存分配的循环,code#2只是一个赋值操作。GC有可能在code#2期间运行,user#2将收到超时。
发布于 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中断。而且同一隔离器中的几个函数永远不能并行运行;只有一个线程可以同时在一个隔离器中活动。
https://stackoverflow.com/questions/59544711
复制相似问题