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