我正在尝试实现一个堆(带有页眉/页脚的隐式自由列表(,并决定是否应该向其添加填充。添加填充的实际好处是什么?我读到它在某种程度上减少了碎片,但我真的不明白为什么会这样。此外,我感兴趣的是在时间方面我能获得什么样的性能优势。
这对我的程序中的本地化也有帮助吗?它有什么帮助?
我应该将整个块填充为4或8字节倍数的格式,还是应该填充除页眉和页脚之外的块。
忘了提一下,这是一个在linux中使用unistd的C实现。
我读到它在某种程度上减少了碎片,但我真的不明白为什么会这样。
这是正确的。它之所以有效,是因为它设置了分配的最小大小。假设您添加填充,使每个块至少为1kB。这意味着,只要新的分配最多为1kB,就永远不会出现释放一块内存的情况,并且在此之后进行的分配将不适合新释放的内存。
你可以在一张纸上做一些简单的实验,很容易地看到这种效果。首先要有一个等于总内存的块大小。当然不会有碎片,但你会浪费很多内存。如果块大小是大小的一半,则基本上是相同的情况,但浪费更少。当我们的块大小是总内存的三分之一时,我们第一次遇到碎片。这将在分配中间块时发生。
简而言之,填充可以减少碎片,但需要更多的内存。
我应该将整个块填充为4或8字节倍数的格式,还是应该填充除页眉和页脚之外的块。
如果您以一种巧妙的方式实现它,那么您只需更改一个变量就可以更改填充大小。因此,找到一种方法来衡量问题,并根据您的需要调整填充。
这也有助于我的程序中的本地化吗?它有什么帮助?
这比较棘手。它可以双向运行,并且取决于使用堆的程序。但我的直觉表明,填充可能会减少局部性。如果是这种情况,这可能会因为缓存未命中而影响性能。
klutt的回答给出了您可能想要一些(重要的(填充的原因。然而,需要一定的最小填充量也是有原因的:对齐。
分配器分配的内存块需要可用于任何数据类型,并且许多数据类型都有某种对齐要求。通常,只是未对齐的数据项使访问像鼻涕虫一样爬行,但某些数据类型可能有硬对齐要求。例如,PPC CPU根本无法从不可被16整除的地址加载矢量(16字节(。这些对准要求是高度特定于平台的。
因此,分配器必须将它返回的任何内存地址对齐到CPU所需的最大对齐(在PPC的情况下为16字节(,并因此将所有内存块填充到该最小内存量。
将内存分配填充到完整的缓存行(X86-64上的64字节,如果我没有错的话(可能是一个明智的想法,但这不是一个要求。
从最小块大小开始,分配器通常将分配增加到二次方或类似的值,以减少他们需要处理的不同内存块大小的数量。