我有一个分配大量内存的应用程序,我正在考虑使用比 malloc 更好的内存分配机制。
我的主要选择是:jemalloc 和 tcmalloc。使用其中任何一个有什么好处吗?
在http://locklessinc.com/benchmarks.shtml中对一些机制(包括作者的专有机制 -- 无锁)进行了很好的比较, 并提到了它们各自的优缺点。
鉴于这两种机制都是活跃的并不断改进。有没有人对这两者的相对表现有任何见解或经验?
我有一个分配大量内存的应用程序,我正在考虑使用比 malloc 更好的内存分配机制。
我的主要选择是:jemalloc 和 tcmalloc。使用其中任何一个有什么好处吗?
在http://locklessinc.com/benchmarks.shtml中对一些机制(包括作者的专有机制 -- 无锁)进行了很好的比较, 并提到了它们各自的优缺点。
鉴于这两种机制都是活跃的并不断改进。有没有人对这两者的相对表现有任何见解或经验?
如果我没记错的话,主要区别在于多线程项目。
两个库都试图通过让线程从不同的缓存中选择内存来消除内存争用,但它们有不同的策略:
jemalloc
(由 Facebook 使用)为每个线程维护一个缓存tcmalloc
(来自谷歌)维护一个缓存池,线程对缓存产生“自然”的亲和力,但可能会改变如果我没记错的话,这再一次导致了线程管理方面的重要差异。
jemalloc
如果线程是静态的,例如使用池,则更快tcmalloc
创建/销毁线程时速度更快还有一个问题是,由于jemalloc
旋转新的缓存以适应新的线程 id,线程的突然峰值将使您在随后的平静阶段(大部分)空缓存。
因此,我会推荐tcmalloc
在一般情况下,并保留jemalloc
用于非常具体的用途(应用程序生命周期内线程数的变化很小)。
我最近考虑将 tcmalloc 用于一个工作项目。这是我观察到的:
大大提高了在多线程设置中大量使用 malloc 的性能。我在工作中将它与一个工具一起使用,性能几乎提高了两倍。原因是在这个工具中,有几个线程在关键循环中执行小对象的分配。使用 glibc,性能会受到影响,因为我认为不同线程中 malloc/free 调用之间的锁争用。
不幸的是,tcmalloc 增加了内存占用。我上面提到的工具会消耗两到三倍的内存(以最大驻留集大小衡量)。增加的内存占用对我们来说是行不通的,因为我们实际上正在寻找减少内存占用的方法。
最后我决定不使用 tcmalloc 而是直接优化应用程序代码:这意味着从内部循环中删除分配以避免 malloc/free 锁争用。(出于好奇,使用一种压缩形式而不是使用内存池。)
给你的教训是,你应该用典型的工作负载仔细衡量你的应用程序。如果您负担得起额外的内存使用量,那么 tcmalloc 对您来说可能会很棒。如果没有,tcmalloc 仍然有助于查看通过避免频繁调用跨线程内存分配会获得什么。
请注意,根据“nedmalloc”主页,现代操作系统的分配器现在实际上非常快:
“Windows 7、Linux 3.x、FreeBSD 8、Mac OS X 10.6 都包含最先进的分配器,并且没有第三方分配器可能在现实世界的结果中显着改善它们”
http://www.nedprod.com/programs/portable/nedmalloc
因此,您可能只需建议您的用户升级或类似的东西就可以逃脱惩罚:)
这里有一个关于分配器的很好的讨论:
你的帖子没有提到线程,但在考虑混合 C 和 C++ 分配方法之前,我会研究内存池的概念。BOOST 有一个很好的。
您还可以考虑使用Boehm 保守垃圾收集器。基本上,您将malloc
源代码中的every 替换为GC_malloc
(etc...),并且您不必费心调用free
. Boehm 的 GC 分配内存的速度并不比 malloc 快(几乎相同,或者可能慢 30%),但它具有自动处理无用内存区域的优势,这可能会改进您的程序(并且肯定会简化编码,因为你不再关心免费)。并且 Boehm 的 GC 也可以用作C++ 分配器。
如果你真的认为这malloc
太慢了(但你应该进行基准测试;大多数malloc
-s 花费不到微秒),并且如果你完全理解程序的分配行为,你可以用你的特殊分配器替换一些 malloc-s(这可以,例如,使用mmap
和自己管理内存的大块从内核中获取内存)。但我相信这样做很痛苦。在 C++ 中,您有分配器的概念std::allocator_traits
,并且大多数标准容器模板都接受这样的分配器(另请参阅std::allocator
),例如,可选的第二个模板参数std::vector
等...
正如其他人建议的那样,如果您认为这malloc
是一个瓶颈,您可以按块(或使用竞技场)或仅在数组中分配数据。
有时,实施专门的复制垃圾收集器(针对您的某些数据)可能会有所帮助。考虑一下MPS。
但是不要忘记过早的优化是邪恶的,请对您的应用程序进行基准测试和分析,以准确了解时间浪费在哪里。