首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >内存分配器建议

内存分配器建议
EN

Stack Overflow用户
提问于 2012-05-22 07:05:19
回答 3查看 255关注 0票数 6

我有一个多线程的部分,其中线程需要分配几个大的数据段,每个段大约100MB,作为缓冲区。此外,可能需要在运行时多次调整缓冲区的大小。

自然的解决方案是使用realloc,但它可能会移动不需要的内存。调整缓冲区大小的free/malloc对恐怕会导致碎片,提前预留内存会产生其他问题。

我可以使用什么来分配/重新分配内存?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-05-22 07:48:11

使用freemalloc。这不会导致碎片问题。

现代分配器对内存碎片的抵抗力相当强。如今,需要一个相当病态的程序才能导致碎片问题。当我们的程序直接寻址物理RAM时,碎片是一个更严重的问题,但是使用虚拟内存,程序堆中的一个大“洞”不需要消耗任何资源。

此外,由于缓冲区的大小,大多数分配器将为每个缓冲区从内核请求一个专用区域。在Linux / OS / BSD上,这意味着每个缓冲区的幕后都有一个匿名mmap。这可能会导致地址空间的碎片,但虚拟地址空间在64位系统上基本上是空闲的,在32位系统上几百兆也不是问题。

所以使用freemalloc

替代方法:你可能会发现让每个缓冲区比你需要的更大会更快。就像malloc在现代Unix上的工作方式一样,任何你不写的页面都不会消耗内存。

所以,如果你malloc一个500MB的缓冲区,但只使用前100MB,你的程序实际上并不会比你malloc一个100MB的缓冲区使用更多的内存。这样可以获得更多的地址空间碎片,但这在64位系统上不是问题,而且您总是可以调整分配大小,以便它也能在32位系统上工作。

至于使用mmap的建议,只需将malloc/free看作是mmap/munmap的一个更简单的接口,这就是它对于大分配的情况(1 MiB是一个常见的阈值)。

票数 5
EN

Stack Overflow用户

发布于 2012-05-22 10:16:24

只需使用realloc即可。在现代系统上,即使缓冲区被移动到一个新地址,移动也是通过操作页表(在Linux、mremap上;我相信其他系统也有类似的机制)而不是通过复制数据来实现的。(请注意,这里我假设的是大缓冲区;对于小缓冲区,通常小于几百kb,将发生实际复制。)

如果您的目标是64位计算机,则完全不需要担心内存碎片。内存碎片永远不会严重到耗尽虚拟地址空间。如果你也需要处理32位机器,只要你没有太多的线程,你可能是安全的。只要总内存消耗小于1 1GB,就很难由于碎片而耗尽虚拟地址空间,假设您的使用模式。如果你担心这个问题,只要预先分配你可能需要的最大大小即可。

票数 4
EN

Stack Overflow用户

发布于 2012-05-22 07:41:19

使用malloc/realloc/free实施您的解决方案,并对其进行分析。如果内存分配有问题,你可以使用更好的malloc实现,比如facebook的jemalloc或者google的tcmalloc

有关这两者的比较,请参阅C++ memory allocation mechanism performance comparison (tcmalloc vs. jemalloc)

它们都非常擅长处理内部/外部碎片。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10693753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档