首页 > 解决方案 > 没有碎片化 stl 容器的大容量内存

问题描述

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

就我而言,我发现有时需要 1 分钟或更长时间才能销毁一个 300GB 的对象。

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

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

谢谢!

标签: c++

解决方案


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

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::mapor之类的容器std::list)。因此,您需要编写一个allocator<T>包含有效池方案的自定义。


推荐阅读