每增加一定字节数的内存分配大小,将如何影响堆碎片化?

3
我在我的C++程序中替换了operator new(),使其分配一个稍微大一些的块来存储额外的数据。因此,该程序执行完全相同的一组分配,只是现在在每个分配中请求多几个字节的内存。除此之外,它的行为完全相同,处理的数据完全相同。该程序在运行时分配大量的块(我想可能是数百万个)不同大小的块。
将每个分配大小增加固定字节数(对于每个分配都相同)如何影响堆碎片化?

1
本地的malloc/new实现已经为您完成了这个操作。堆分配器已经非常复杂了,因此尝试进行这样的优化可能会使情况变得更糟。 - Mike Weller
@Mike Weller:我在哪里进行了优化? - sharptooth
你为什么做出这个改变? - Mike Weller
@Mike Weller:我需要这个来跟踪分配并简化内存泄漏检测。 - sharptooth
4个回答

2

除非您的程序使用一些“边缘”块大小(比如接近2的幂),否则我认为块大小(或与标准分配程序相比的小差异)不会影响碎片化。对于数百万个分配,一个好的分配器会填满空间并有效地管理它。

反过来想,如果您的程序最初使用的块大小与修改后的分配器相同,那么您会关心在这种情况下的内存碎片问题吗?


1

如果您的块(已分配和释放的内存)仍然比C库分配器处理时没有碎片问题的块小,那么您不必面对任何内存碎片。例如,请看看我自己关于分配器的问题:Small block allocator on Linux (or RedHat Linux) to avoid memory fragmentation

换句话说,您已经实现了自己的::operator new(),并在其中调用malloc()并传递稍大的块大小。malloc()在C库中,它不仅负责分配和释放,还负责避免内存碎片。如果您不经常分配和释放大于分配器可以有效处理的块大小,则可以预期不会有内存碎片。


1

堆通常被实现为单元格的链表。在应用程序启动时,只有一个大单元格。您的第一个分配会从开头断开一小块,以创建一个新的已分配堆单元格。随后的分配也是如此。一段时间后,一些单元格被释放,留下已分配块之间的空闲空间。

运行一段时间后,当您请求分配时,分配器会遍历堆,直到找到与所请求的大小相等或更大的空闲单元格。将单元格分配大小向上舍入可能需要更多的内存,但增加了找到合适的空闲单元格的可能性,这意味着不必将新内存添加到堆的末尾。这可能会提高性能。

然而,请记住,堆操作很昂贵,因此应该尽量减少。您很可能正在分配和释放相同类型和大小的对象。请考虑使用专门的自由列表来保存您的对象。这将节省堆操作,从而最小化碎片化。STL具有此目的的分配器。


1

这取决于驱动内存分配器的实现,例如: 在Windows上,它从进程堆中提取内存,在XP下,此堆未设置为低碎片化实现,这可能会给工作带来很大的困扰。

在基于Bin或Slab的分配器下,您少量的额外字节可能会将其推向下一个块大小,浪费大量的内存并导致可怕的虚拟内存抖动。

根据您的内存使用需求,使用自定义分配器来替换:: new可能更好,例如Hoard或nedmalloc。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接