内存分配器建议

时间:2012-05-21 23:05:19

标签: c optimization memory

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

自然的解决方案是使用realloc,但它可能会移动不需要的内存。 free/malloc对调整缓冲区大小,我担心可能导致碎片并在手工创建其他问题之前保留内存。

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

3 个答案:

答案 0 :(得分:5)

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

现代分配器对内存碎片具有相当的抵抗力。这些天,它需要一个相当病态的程序来导致碎片问题。当我们的程序直接处理物理RAM时,碎片是一个更严重的问题,但是对于虚拟内存,程序堆中的大“漏洞”不需要消耗任何资源。

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

因此请使用freemalloc

替代方案:您可能会发现让每个缓冲区大于您所需的速度更快。 malloc在现代Unix上运行的方式,你不写的任何页面都不消耗内存。

因此,如果您malloc 500 MB缓冲区但只使用前100 MB,那么您的程序实际上不会使用比malloc 100 MB缓冲区更多的内存并使用整个内存。通过这种方式可以获得更多的地址空间碎片,但这在64位系统上不是问题,您可以随时调整分配大小,以便它也可以在32位系统上运行。

至于使用mmap的建议,只需将malloc / free视为mmap / munmap的简单界面,这就是它的含义对于大型分配(1 MiB是一个常见的阈值)。

答案 1 :(得分:4)

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

如果您的目标是64位计算机,则完全不需要担心内存碎片。你永远不会破坏内存,以至于耗尽虚拟地址空间。如果你也需要处理32位机器,只要你没有太多的线程,你就可以安全了。只要总内存消耗小于1GB,由于碎片,假定您的使用模式就很难用尽虚拟地址空间。如果您对此感到担心,只需预先分配您可能需要的最大尺寸。

答案 2 :(得分:1)

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

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

他们都善于处理内部/外部碎片。