内存碎片是否会减缓New/Malloc的速度?

5

背景介绍:

我正在开发一个需要运行数月并使用动态分配的系统。

问题:

我听说内存碎片化会减慢 new malloc 运算符的速度,因为它们需要在内存中查找一个“空洞”,而不是在堆中直接“向前走”。

我读了以下问题:什么是内存碎片化?

但回答中没有涉及性能问题,只提到分配大块内存时失败的情况。

那么内存碎片化是否会使 new 分配内存所需时间更长? 如果是,会增加多少时间? 我如何知道 new 在堆中查找内存时遇到了“困难”?

我曾尝试找出GCC用于查找内存中“空洞”的数据结构/算法。 但是没有找到任何合理的解释。


同一台机器上运行的其他应用程序和服务可能会影响内存碎片化。 - Ripi2
6
如果你非常需要动态分配内存,那么就接受底层系统已经有了优化良好的算法来处理碎片问题。虽然这听起来像是临终前的遗言,但相比担心这些问题所花费的时间,这是最好的选择。 - DeiDei
2
“我正在开发一个需要运行数月并使用动态分配的系统。”-- 这是你的第一个错误 :) 。说真的,最好设计一个可以重新启动应用程序的系统,而不是期望它在数月内无故障地运行。这样,您还可以应对停电、必要的系统重启、操作系统/其他应用程序故障等情况。 - Dave S
除非您有一个明确的问题,已经确定内存分配是瓶颈,并且这个瓶颈是由于堆碎片而引起的,否则这听起来像是过早优化。 - spectras
.NET的示例很好:它展示了一种不同的分配器策略,利用了.NET中对象引用使用不透明句柄结构而不是直接地址的事实,这使得它可以移动对象以压缩堆,消除碎片化。此外,它将分配区域分割成大小桶,有助于减轻首先出现的碎片问题。然而,移动对象的能力带来了所有引用使用的额外间接性。权衡... - spectras
显示剩余2条评论
1个回答

7

内存分配是平台特定的,取决于平台。

我想说 “是的,new 分配内存需要时间。分配时间取决于许多因素,如算法、碎片化程度、处理器速度、优化等等。

关于分配时间的最佳答案是进行性能分析和测量。编写一个简单的程序来使内存碎片化,然后测量分配内存所需的时间。

程序没有直接方法来发现可用内存位置的难度。您可以读取时钟,分配内存,然后再次读取。另一个想法是设置一个计时器。

注意:在许多嵌入式系统中,动态内存分配是不受欢迎的。在关键系统中,碎片化可能是敌人。因此,使用固定大小的数组。在编译时进行固定大小的内存分配(在编译时),可以消除碎片化作为缺陷问题。

编辑1:搜索
通常,内存分配需要调用函数。这样做的影响是处理器可能必须重新加载其指令缓存或流水线,从而消耗额外的处理时间。还可能有额外的指令传递参数,例如最小大小。在编译时的局部变量和分配通常不需要为分配调用函数。

除非分配算法是线性的(考虑数组访问),否则它将需要找到可用插槽的步骤。一些内存管理算法基于请求的大小使用不同的策略。例如,某些内存管理器可能具有专门针对 64 位或更小的大小的池。

如果您将内存管理器视为块的链接列表,则管理器将需要找到第一个大于或等于请求的块。如果该块大于所请求的大小,则可以将其拆分,并将剩余的内存创建为新块并添加到列表中。

没有标准的内存管理算法。它们根据系统的需求而异。内存管理器适用于内存受限(小)的平台将不同于具有大量内存的平台。关键系统的内存分配可能与非关键系统的内存分配不同。C++ 标准不规定内存管理器的行为,只规定了一些要求。例如,内存管理器允许从硬盘或网络设备分配。

影响的重要性取决于内存分配算法。最佳路径是在目标平台上测量性能。


你能详细说明一下为什么 new 操作需要更多时间吗?问题具体是什么?影响有多大? - OopsUser
请查看我的最新编辑。此外,请在互联网上搜索“内存分配算法”和“操作系统理论”。 - Thomas Matthews

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