我目前有大量的多线程服务器应用程序,并且我正在寻找一个好的多线程内存分配器。

到目前为止,我在以下两点之间左右为难:

  • 太阳乌梅
  • 谷歌的 tcmalloc
  • 英特尔的线程构建块分配器
  • 埃默里·伯杰的宝藏

据我所知,hoard 可能是最快的,但我在今天之前没有听说过它,所以我怀疑它是否真的像看起来那么好。有人有尝试这些分配器的个人经验吗?

有帮助吗?

解决方案

我使用过 tcmalloc 并阅读了有关 Hoard 的文章。两者都有相似的实现,并且都实现了相对于线程/CPU 数量的大致线性性能扩展(根据各自站点上的图表)。

所以:如果性能确实如此重要,那么就进行性能/负载测试。否则,只需掷骰子并选择列出的其中之一(根据目标平台上的易用性进行加权)。

并从 trshiv 的链接, ,看起来 Hoard、tcmalloc 和 ptmalloc 的速度都大致相当。总的来说,tt 看起来 ptmalloc 是为了占用尽可能少的空间而优化的,Hoard 是为了速度 + 内存使用的权衡而优化的,而 tcmalloc 是为了纯粹的速度而优化的。

其他提示

真正判断哪种内存分配器适合您的应用程序的唯一方法是尝试一些。提到的所有分配器都是由聪明人编写的,并且将在一个特定的微基准测试上击败其他分配器。如果您的应用程序一整天所做的就是在线程 A 中 malloc 一个 8 字节块并在线程 B 中释放它,并且根本不需要处理其他任何事情,那么您可能可以编写一个内存分配器来击败任何一个到目前为止列出的那些。它对于其他方面来说不会很有用。:)

我在我工作的地方有一些使用 Hoard 的经验(足够多,以至于在最近的 3.8 版本中解决了一个更隐蔽的错误,因为这种经验而被发现)。这是一个非常好的分配器 - 但对您来说有多好取决于您的工作量。而且你确实必须支付 Hoard 费用(尽管它不是太贵)才能在商业项目中使用它而不需要对你的代码进行 GPL 许可。

稍作修改的 ptmalloc2 已经成为 glibc 的 malloc 背后的分配器已有相当长一段时间了,因此它得到了令人难以置信的广泛使用和测试。如果稳定性比一切都重要,那么它可能是一个不错的选择,但你没有在列表中提到它,所以我假设它已经被淘汰了。对于某些工作负载来说,这是很糟糕的 - 但对于任何通用 malloc 来说也是如此。

如果你愿意付钱(而且根据我的经验,价格是合理的), 智能堆SMP 也是一个不错的选择。提到的大多数其他分配器都被设计为可以 LD_PRELOAD 的直接 malloc/free new/delete 替代品。SmartHeap 也可以这样使用,但它还包括一个完整的与分配相关的 API,可让您根据自己的喜好微调分配器。在我们所做的测试中(同样,非常针对特定应用程序),当作为直接 malloc 替代品时,SmartHeap 的性能与 Hoard 大致相同;两者之间的真正区别在于定制程度。您需要分配器的通用性越低,您就能获得更好的性能。

根据您的用例,通用多线程分配器可能根本不是您想要使用的;如果您不断地分配和释放大小相同的对象,您可能只想编写一个简单的平板分配器。Linux 内核中的多个地方使用了平板分配,符合该描述。(我会给你一些更有用的链接,但我是一个“新用户”,Stack Overflow 已经决定不允许新用户 一个答案很有帮助。不过,谷歌可以提供足够的帮助。)

我个人更喜欢并推荐 ptmalloc 作为多线程分配器。Hoard 不错,但是在我的团队几年前对 Hoard 和 ptmalloc 进行的评估中,ptmalloc 更好。据我所知,ptmalloc 已经存在很多年了,并且作为多线程分配器被广泛使用。

你可能会发现 这个比较 有用。

也许这是处理您所问问题的错误方法,但也许可以完全采用不同的策略。如果您正在寻找一个非常快速的内存分配器,也许您应该问为什么您需要花费所有时间来分配内存,而您也许可以摆脱变量的堆栈分配。堆栈分配虽然更烦人,但如果做得正确,可以避免大量互斥争用,并避免代码中出现奇怪的内存损坏问题。此外,碎片可能会减少,这可能会有所帮助。

我们在几年前工作的一个项目中使用了hoard。看起来效果很好。我对其他分配者没有经验。尝试不同的方法并进行负载测试应该很容易,不是吗?

locklessinc 分配器非常好,如果您有疑问,开发人员会及时回复。他写了一篇关于所使用的一些优化技巧的文章,读起来很有趣: http://locklessinc.com/articles/allocator_tricks/. 。我过去曾使用过它,效果非常好。

enter image description here

可能对你的问题的答复很晚,但是

如果性能出现问题,为什么还要进行 malloc 呢?

更好的方法是在初始化时对一个大内存窗口进行 malloc,然后提出一个 light weight Memory manager 那会 lease out the memory chunks at run time.

这可以避免堆扩展时发生系统调用的任何可能性。

你可以试试 ltalloc (具有快速池分配器速度的通用全局内存分配器)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top