我想知道realloc()确实需要多少性能:我经常这样做是为了将可用内存区域扩展一个元素(=特定结构)。是 - 感谢MMU - 这样的realloc()只是保留存储区的扩展,还是在某些条件下可以完全复制所有可以想到的数据?
据我所知,std :: vector经常需要在内存区域大小增加时复制内存区域并且预定义的内存量太小...
答案 0 :(得分:3)
realloc
复制所有数据。假设其他任何东西只是要求性能问题。 realloc
可以避免复制的情况很少,你绝对不应该依赖它们。我已经看到realloc
的多个实现,甚至无法实施代码以避免复制,因为它不值得付出努力。
MMU与它无关,因为重新映射支持分配的内存页面的成本不会有所回报,直到您达到两页以上为止。这是基于我15年前读过的研究,从那以后内存复制变得更快,而内存管理由于MP系统而变得更加昂贵。这也仅适用于内核中的零拷贝方案,而不会传递系统调用开销,这很重要,并且会减慢这里的速度。它还需要您的分配完全对齐和调整大小,从而进一步降低以这种方式实施realloc
的实用性。
最好realloc
可以避免复制数据,如果没有分配它将扩展到的内存块。如果realloc
是你的应用程序唯一的东西,你可能会幸运,但只要有一点点碎片或其他东西分配,你运气不好。始终假设realloc为malloc(new_size); memcpy(new, old, old_size); free(old);
。
处理使用realloc
调整数组大小时的一个好习惯是跟踪阵列中有多少元素并具有单独的容量。仅在元素数量达到容量时才增加容量和realloc
。在每个realloc上增加1.5倍的容量(大多数人做2倍,它通常在文献中被推荐,但研究表明2x会导致非常糟糕的内存碎片问题,而1.5x几乎同样有效并且内存更好)。像这样:
if (a->sz == a->cap) {
size_t ncap = a->cap ? a->cap + a->cap / 2 : INITIAL_CAP;
void *n = realloc(a->a, ncap * sizeof(*a->a));
if (n == NULL)
deal_with_the_error();
a->a = n;
a->cap = ncap;
}
a->a[a->sz++] = new_element;
如果包含数组的结构初始化为零,则即使对于初始分配也是如此。
答案 1 :(得分:1)
复制数据并不是昂贵的部分(尽管有些人可能不同意)。点击嵌入式 malloc 和免费是很昂贵的,并且几乎可以占用所有的执行时间,具体取决于您正在做的其他事情。 如果是这样,修复它应该会给你一个大加速。
This是我如何判断事情花费的时间。
最简单的解决方案是减少频率。分配数组时,将其分配得特别大,然后跟踪自己实际使用的数量。
答案 2 :(得分:0)
行为实际上取决于实施。但所有人都试图尽量减少重新安置内存的成本。因为重新定位对于性能而言非常昂贵。它对缓存有直接影响。我没有数字,但操作非常昂贵
例如,在重定位的情况下,如果运行时面临重新定位内存或扩展当前保留内存的两个选项,则选择后者。
但它并不像我说的那么简单。它还必须考虑内存碎片
因此,需要进行多项权衡才能满足
如果你提到vector
,他们会使用不同的方案。如果vector
保留m
个字节,并且需要额外的n
个字节,则运行时将分配2 * (n+m)
以最大限度地减少将来重定位的可能性。如果您超过新尺寸,则下次使用系数4
代替2
;等等。我提到的数字并不真实
我不太了解实现,希望其他人给你更具体的信息。