分配内存的权力是两个更好吗?

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

 //char *ptr= malloc( 200 ); char *ptr= malloc( 256 );//instead of 200 we use 256 

如果给两个大小的大小比较好,那是什么原因呢? 为什么更好?

谢谢

编辑

我的困惑的原因是从乔尔的博客回到基础引用

聪明的程序员通过总是分配大小为2的内存块来最小化malloc的潜在破坏。 你知道,4字节,8字节,16字节,18446744073709551616字节等等。对于任何使用乐高的人来说,这应该是直观的,这样可以最大限度地减less自由链中奇怪的碎片数量。 虽然这看起来像是浪费空间,但也很容易看出它从来不会浪费掉超过50%的空间。 所以你的程序使用的内存不会超过它所需要的两倍,这并不是什么大不了的事情。

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

到目前为止,大多数回复都表示,用两个幂来分配内存是一个坏主意,那么在哪种情况下,最好遵循Joel关于malloc()的观点? 他为什么这么说? 以上引用的build议是否已经过时了?

请解释一下。
谢谢

只要给出你需要的确切大小。 “幂次幂”可能是“更好”的唯一原因是允许更快的分配和/​​或避免内存碎片。

然而,任何涉及到高效的非平凡的malloc实现将在内部以这种方式整理分配,只要这样做是合适的。 你不需要关心“帮助”malloc; malloc可以自行完成。

编辑:

为了回应Joel在软件方面的文章,Joel在这一节中指出(如果没有引用的段落的上下文,很难正确辨别),如果您期望经常重新分配缓冲区,那么最好用乘法的方式来做,而不要加成。 实际上,这正是C ++(和其他)中的std::stringstd::vector类所做的。

这是一个改进的原因不是因为你通过提供方便的数字来帮助malloc ,而是因为内存分配是一个昂贵的操作,并且你正在尽量减less你的操作次数。 乔尔提出了一个时间 – 空间折衷的具体例子。 他认为,在很多情况下,需要的内存量是dynamic变化的,最好是浪费一些空间(在每次扩展时分配最多两倍的空间),以节省反复使用所需的时间正好在n个字节的内存中,每次你需要n个字节。

乘数并不一定是两个:你可以根据需要分配多达三倍的空间,最后分配三个幂的分配,或者分配最多五十七倍的空间,分配五十七个权力。 分配越多,你需要重新分配的次数越less,但是你将浪费的内存越多。 按照需要分配两倍的权力,使用最多两倍的内存,恰好是一个很好的起始点权衡,除非你更清楚地知道你的需求是什么。

他确实提到,这有助于减less“自由链条中的分裂”,但原因更多的是由于分配的数量和统一性,而不是确切的规模。 一方面,分配和释放内存的次数越多,无论分配的是多less,分割堆的可能性就越大。 其次,如果您有多个缓冲区,您使用相同的乘法resizealgorithmdynamicresize,那么很可能如果resize从32到64,另一个从16调整到32,那么第二个重新分配可以适合第一个以前是。 如果一个人从25岁调整到60岁,另一个从16岁调整到26岁,情况就不会这样了。

再说一遍,如果你只做一次分配步骤,那么他所说的都不适用。

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

假设我们将15000个字符附加到QStringstring。 然后,当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,每次增加一倍。 更准确地说,它前进到下一个二的幂,减去12.( 一些内存分配器在要求两个精确的幂时执行最差 ,因为它们使用每个块的几个字节用于簿记)。从4084开始,它以块2048个字符(4096字节)。 这是有道理的,因为现代操作系统在重新分配缓冲区时不会复制整个数据 。 物理内存页面被简单地重新sorting,只有第一页和最后一页上的数据实际上需要被复制。

我喜欢他们希望在智能手机和服务器场中performance良好的代码操作系统function。 鉴于他们比我更聪明,我认为所有现代操作系统都可以使用该function。

可能是真的,但肯定不会更好。

只要分配你需要的内存,当你需要的时候,尽快将它释放。

有太多的程序是浪费资源 – 不要让你的其中一个。

这有点不相干。

Malloc实际上分配的内存比请求的要多一些,因为它有自己的头文件来处理。 因此,最佳的存储可能类似于4k-12字节…但是取决于实现而变化。

在任何情况下,你都没有理由把你需要的存储空间作为一个优化技术。

可能希望根据处理器的字大小来分配内存; 没有任何2的老势力会做。

如果处理器有32位字(4字节),则以4字节为单位进行分配。 按2字节分配可能没有帮助,因为处理器更喜欢数据在4字节边界上开始。

另一方面,这可能是一个微观优化。 大多数内存分配库设置为返回在正确位置alignment的内存,并将保留最less量的碎片。 如果您分配15个字节,库可能会填充并分配16个字节。 有些内存分配器根据分配大小有不同的池。

总之,分配你需要的内存量。 让分配库/pipe理器为您处理实际的金额。 把更多的精力放在正确性和稳健性上,而不是担心这些微不足道的问题。

当我分配一个缓冲区,可能需要保持增长以容纳尚未知的大小的数据时,我开始以2减1的幂,并且每次运行空间不足,我重新分配两倍的以前的大小加上1.这使得我不必担心整数溢出; 当前一个大小是SIZE_MAX时,大小只能溢出,此时分配已经失败了, 2*SIZE_MAX+1 == SIZE_MAX无论如何。

相比之下,如果我只是使用2的幂次,每次翻倍,我可能会成功得到一个2 ^ 31字节的缓冲区,然后重新分配给一个0字节的缓冲区,下一次我加倍的大小。

正如一些人所说的,2-minus-12的功耗对于某些malloc的实现是有好处的,我们可以同样以2减12的功率开始,然后加倍并在每一步添加12。

另一方面,如果您只是分配不需要增长的小缓冲区,请准确地请求所需的大小。 不要试图猜测对malloc有什么好处。

这完全依赖于给定的malloc(3) libc实现。 这取决于它认为合适的顺序保留堆块。

为了回答这个问题 – 不,这不是“更好”(这里的“更好”是指…?)。 如果你要求的尺寸太小, malloc(3)会在内部预留更大的块,所以只要坚持你的确切大小。

随着今天的内存量和速度,我不认为这是相关的了。

而且,如果您要频繁分配内存,最好考虑定制内存池/预分配。

总是有testing…

你可以尝试一个循环分配内存的“样本”程序。 通过这种方式,你可以看到你的编译器神奇地分配内存2的权力。有了这些信息,你可以尝试使用2策略分配相同数量的总内存:随机大小的块和2大小块的功率。

我只希望有大量的内存差异,如果有的话。

如果你正在分配某种可扩展的缓冲区,你需要为初始分配select一些数字,那么是的,2的幂是可以select的好数字。 如果你需要为struct foo分配内存,那么只需要malloc(sizeof(struct foo))。 关于2次幂分配的build议源于内部碎片的低效率,但是针对多处理器系统的现代malloc实现开始使用CPU本地池进行足够小的分配,这样可以防止以前的locking争用当多个线程同时尝试malloc时会导致结果,并且由于碎片而花费更多的时间。

通过仅分配所需的内容,可以确保数据结构在内存中的打包密度更高,从而提高caching命中率,这比内部碎片对性能影响更大。 有一些很老的malloc实现和非常高端的多处理器系统,其中明确的填充分配可以提供一个加速,但是在这种情况下,你的资源最好用在一个更好的malloc实现上运行。 预填充还会使代码的可移植性降低,并且阻止用户或系统在运行时以编程方式或环境variablesselectmalloc行为。

不成熟的优化是万恶之源。

重新分配时,您应该使用realloc()而不是malloc()。 http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/

总是使用两个幂的? 这取决于你的程序在做什么。 如果你需要重新处理你的整个数据结构,当它增长到2的幂,是的,这是有道理的。 否则,只分配你需要的东西,而不要占用内存。