【问题标题】:How will increasing each memory allocation size by a fixed number of bytes affect heap fragmentation?将每个内存分配大小增加固定字节数会如何影响堆碎片?
【发布时间】:2011-05-23 10:51:05
【问题描述】:

我在我的 C++ 程序中替换了 operator new(),以便它 allocates a slightly bigger block to store extra data。所以程序执行完全相同的分配集,只是现在它在每次分配中请求更多字节的内存。否则它的行为是完全一样的,它处理完全相同的数据。该程序在其运行期间分配了许多不同大小的块(我想是数百万块)。

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

【问题讨论】:

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

标签: c++ memory memory-management


【解决方案1】:

如果您的块(已分配和已解除分配的内存)仍然比 C 库分配器处理的小而不会出现碎片问题,那么您一定不会遇到任何内存碎片。例如,看看我自己关于分配器的问题:Small block allocator on Linux (or RedHat Linux) to avoid memory fragmentation

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

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

      但是,请记住,堆操作代价高昂,因此应尽量减少。您很可能正在分配和释放相同类型的对象,因此大小相同。考虑为您的对象使用专门的空闲列表。这将节省堆操作,从而最小化碎片。正是出于这个原因,STL 有分配器。

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-02-15
          • 2021-02-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-09
          • 1970-01-01
          相关资源
          最近更新 更多