以2的幂分配内存是否更好?

And*_*sne 40 c malloc memory-management

当我们使用malloc()分配内存时,我们应该给出两个幂的大小吗?或者我们只是给出我们需要的确切尺寸?
喜欢

//char *ptr= malloc( 200 ); 
char *ptr= malloc( 256 );//instead of 200 we use 256
Run Code Online (Sandbox Code Playgroud)

如果给出2的幂的大小更好,那是什么原因?为什么更好?

谢谢

编辑

我混淆的原因是在Joel的博客Back to Basics中引用

智能程序员通过始终分配大小为2的内存块来最小化malloc的潜在破坏.你知道,4个字节,8个字节,16个字节,18446744073709551616个字节等.由于任何使用乐高的人都应该直观的原因,这可以最大限度地减少自由链中发生的奇怪碎片的数量.虽然看起来这似乎浪费了空间,但也很容易看出它永远不会浪费50%以上的空间.所以你的程序使用的内存不会超过它需要的两倍,这不是什么大不了的事.

对不起,我应该早点发布上面的报价.我很抱歉!

到目前为止,大多数回复都说,以2的力量分配内存是一个坏主意,那么在哪种情况下更好地遵循Joel的观点malloc()呢?他为什么这么说?以上引用的建议现在已经过时了吗?

请解释一下.
谢谢

Tyl*_*nry 54

只需给出您需要的确切尺寸.两个幂的大小可能"更好"的唯一原因是允许更快的分配和/​​或避免内存碎片.

但是,任何malloc关注高效的非平凡实现都会以这种方式在内部围绕分配,如果适当的话.你不需要关心"帮助"malloc; malloc可以自己做得很好.

编辑:

为了回应你对Joel on Software文章的引用,Joel在该部分中的观点(如果没有你引用的段落之后的上下文很难正确辨别),如果你希望经常重新分配一个缓冲区,它就是更好地这样做是乘法的,而不是相加的.事实上,这正是C++(以及其他)中的std::stringstd::vector类所做的.

这是一个改进的原因不是因为你malloc通过提供方便的数字来帮助,而是因为内存分配是一项昂贵的操作,并且你正在努力减少你执行它的次数.乔尔提出了一个时空权衡概念的具体例子.他认为,在需要大量内存动态变化的许多情况下,最好浪费一些空间(通过在每次扩展时分配最多两倍的空间),以节省重复粘贴所需的时间.n每次需要n更多字节时,确切地说就是内存字节数.

乘数不必是两个:您可以根据需要分配最多三倍的空间,最终得到三次幂的分配,或者分配多达五十七倍的空间,最终分配权力为五十七.您执行的分配越多,重新分配所需的频率就越低,但浪费的内存就越多.分配两个权力,最多使用两倍的内存,恰好是一个很好的起点权衡,除非你更好地了解你的需求是什么.

他确实顺便提一下,这有助于减少"自由链中的碎片化",但其原因更多是因为分配的数量和一致性,而不是它们的确切大小.首先,分配和释放内存的次数越多,分割堆的可能性就越大,无论分配的大小是多少.其次,如果你有多个缓冲区,你使用相同的乘法调整大小算法动态调整大小,那么很可能如果一个调整大小从32调整到64,另一个调整大小从16调整到32,那么第二个重新分配可能适合第一个以前是.如果一个人从25改为60,另一个从16改为26,则情况并非如此.

而且,如果你只打算进行一次分配步骤,那么他所说的都不适用.

  • Qt人似乎认为"一些内存分配器在请求2的精确幂时表现最差,因为它们每个块使用几个字节用于簿记".当你选择自己的方案时,请考虑一下. (4认同)
  • 你说对了.例如,如果您要编写自己的堆栈实现,只有当推入堆栈的项目数超过您拥有的空间量时,才会内部增加分配给它的内存.在这种情况下,为了节省时间,每次达到限制时,您将在堆栈中分配的空间加倍.这是一个好主意,因为如果你只为这一个额外项目分配了足够的空间,那么你必须每隔*时间(这是昂贵且不必要的). (2认同)

Gyö*_*sek 18

只是扮演魔鬼的拥护者,这就是Qt如何做到的:

假设我们在QString字符串中附加了15000个字符.然后,当QString空间不足时,发生以下18次重新分配(可能的15000次):4,8,12,16,20,52,116,244,500,1012,2036,4084,6132,8180,10228, 12276,14324,16372.最后,QString分配了16372个Unicode字符,其中15000个被占用.

上面的值可能看起来有点奇怪,但这里有指导原则:

QString一次分配4个字符,直到达到大小20.从20到4084,每次加倍大小.更确切地说,它进入下一个2的幂,减去12.(当请求2的精确幂时,一些内存分配器执行最差,因为它们每个块使用几个字节用于簿记.)从4084开始,它按块进行2048个字符(4096个字节).这是有道理的,因为现代操作系统在重新分配缓冲区时不会复制整个数据 ; 物理内存页面只是重新排序,实际上只需要复制第一页和最后一页上的数据.

我喜欢他们预期代码中的操作系统功能的方式,这些功能意味着从智能手机到服务器群都能很好地运行.鉴于他们比我更聪明,我认为所有现代操作系统都可以使用所述功能.

  • 偏离主题,但我喜欢在Unicode 2.0之后的14年,那些犯了选择16位wchar类型错误的人仍然将UTF-16代码单元称为Unicode"字符"...... (9认同)

Chr*_*isF 6

可能曾经是真的,但肯定不会更好.

只需在需要时分配所需的内存,并在完成后立即释放.

有太多的程序浪费资源 - 不要让你的其中之一.