繁体   English   中英

批量内存没有碎片stl容器

[英]Bulk memory free of fragmented stl containers

目前,当我们想要破坏具有非常分散的内存分配的复杂对象的非常大的嵌套列表/映射时,我假设C ++是调用析构函数并逐个释放内存并递归,这需要花费大量时间并且效率低下?

在我的情况下,我发现有时需要1分钟或更长时间才能破坏300GB的物体。

操作系统可以杀死占用大量内存的进程,因为它只是释放所有内存而不考虑内部逻辑进程。

我想知道是否有任何现有的C / C ++库可以做到这一点? 提供维护id系统的自定义内存分配器? 这样,如果我指定一个id来为给定的大型STL容器(及其元素)创建一个分配器。 当我想要破坏它时,我可以释放分配了指定id的所有内存,并且只丢弃指向外部容器的指针(它会跳过所有的析构函数)? 就像我们可以“杀死”一个pid ......

谢谢!

这可以通过池分配器和新的放置来完成,当然你会有一些限制,比如找到池中插槽的通用大小(如果你不想要精细的粒度),但通常一个简单的案例场景就像以下:

struct Foo {
  double x, y;
  Foo(double x, double y) { this->x = x; this->y = y; };
};

std::byte* buffer = new std::byte[sizeof(Foo) * 10];

Foo* foo1 = new(buffer) Foo(1.0, 2.0);
Foo* foo2 = new(buffer + sizeof(Foo)) Foo(1.0, 2.0);

delete[] buffer;

解释了基本原理。 这必须采取预防措施,因为没有人调用你的析构函数(你应该通过foo1->~Foo()手动完成)。 但是如果析构函数没有副作用,或者您可以立即处理它们,那么标准允许您不要明确地调用它。

现在棘手的部分是,如果你正在使用STL集合,那么他们会在内部进行大量的分配来存储他们的需求(特别是像std::mapstd::list这样的容器)。 所以你需要编写一个自定义allocator<T>来包装一个有效的池方案。

如果您想要有效freeing内存,那么执行单个删除是可行的方法。 虽然请记住,释放内存并不是删除调用所做的唯一事情。 它也称为析构函数。 如果不是微不足道或不可见,您的编译器仍然必须通过函数调用来调用它。

也就是说,尽可能使用std::vector 我已经在向量之上编写了自定义集和映射,功能较少(没有删除),以获得内存和性能。

如果你有很多小物体,比如通常需要1,2,...... 16个元素的矢量,你可以通过使用更多的内存来获得速度。 boost小向量和其他容器可以帮助您不分配。 在算法中使用它,已经在真实世界代码中节省了显着的百分比(> 90%)。

最后,你不能总是赢。 如果您可以估计内存使用情况,或已经接近的情况,可以使用[ https://howardhinnant.github.io/stack_alloc.html ] ( Howard Hinnant的堆栈分配器)。 不要被名字所迷惑,你也可以在堆上分配内存。 通过一些操作,我怀疑你应该能够改变它以接受运行时大小。 但是,它并不完美,你可以覆盖很大一部分。

也就是说,您总是可以故意创建内存泄漏,但这可能会消除析构函数的副作用。 您可以从地图中提取节点 ,并将它们存储在已分配的矢量中。 这可能会跃入UB,我不是那里的专家。

哦,最后,你可以继承标准的allocator,只覆盖deallocate函数。 查看全局以确定是否要调用实际的deallocate。 翻转开关,并在退出时进行内存泄漏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM