如何通过固定的字节数增加每个内存分配大小会影响堆碎片?

时间:2010-12-10 11:47:44

标签: c++ memory memory-management

我在我的C ++程序中替换了operator new(),因此它allocates a slightly bigger block to store extra data。因此,程序执行完全相同的分配集,但现在它在每次分配中请求多个字节的内存。否则它的行为完全相同,它处理完全相同的数据。该程序在运行时分配了许多不同大小的块(数百万,我猜)。

如何将每个分配大小增加固定的字节数(每个分配都相同)会影响堆碎片?

4 个答案:

答案 0 :(得分:2)

除非你的程序使用一些“边缘”块大小(例如,接近2的幂),否则我看不到块大小(或块大小与标准分配的程序相比的小差异)可能会影响碎片。有了数百万的分配,一个好的分配器可以填补空间并有效地管理它。

相反地思考,假设您的程序最初使用的块大小与修改后的分配器相同。在那种情况下你会不会为内存碎片而烦恼?

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

堆通常作为单元格的链接列表实现。在应用程序启动时,只有一个大型单元。您的第一个分配在开始时中断了一小部分以创建新的已分配堆单元。后续分配也是如此。过了一会儿,一些细胞被释放,在分配的块之间留下了自由孔。

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

但是,请记住堆操作很昂贵,因此应尽量减少。您最有可能分配和释放相同类型的对象,因此大小相同。考虑为您的对象使用专门的免费列表。这将保存堆操作,从而最大限度地减少碎片。由于这个原因,STL有分配器。

答案 3 :(得分:1)

这取决于驱动内存分配器的实现,例如: 在寡妇身上,它从进程堆中提取内存,在XP下,这个堆没有被设置为低碎片实现,这实际上可以在工作中抛出一个扳手。

在基于bin或slab的分配器下,你的几个额外字节可能会将它推到下一个块大小,疯狂浪费内存并导致可怕的虚拟内存抖动。

根据您的内存使用需求,使用自定义allacator替换::new可能会更好,例如hoard或nedmalloc。