用于C / C ++的多线程内存分配器

时间:2020-03-06 14:51:29  来源:igfitidea点击:

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

到目前为止,我陷入了两难之间:

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

从我发现的ho积可能是最快的,但是直到今天我还没有听说过它,所以我对它的真实性表示怀疑。任何人都有尝试这些分配器的个人经验吗?

解决方案

也许这是处理我们要问的问题的错误方法,但是也许可以完全采用另一种策略。如果我们正在寻找一个真正快速的内存分配器,也许我们应该问为什么当我们可能只是不用变量的堆栈分配时,为什么需要花所有这些时间分配内存。堆栈分配虽然很烦人,但正确完成可以节省互斥锁争用的方式,并且可以避免代码中出现奇怪的内存损坏问题。此外,我们可能会有更少的碎片,这可能会有所帮助。

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

我用过tcmalloc并阅读了有关Hoard的信息。两者都具有相似的实现方式,并且都相对于线程/ CPU的数量(根据它们各自站点上的图形)实现了大致线性的性能缩放。

因此:如果性能确实至关重要,那么请进行性能/负载测试。否则,只要掷骰子,然后选择列出的骰子之一即可(通过在目标平台上的易用性进行加权)。

从trshiv的链接看来,Hoard,tcmalloc和ptmalloc的速度都差不多。总体而言,tt看起来ptmalloc已针对占用尽可能少的空间进行了优化,Hoard针对速度与内存使用之间的折衷进行了优化,而tcmalloc针对纯速度进行了优化。

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

我们可能会发现此比较有用。

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

我在使用Hoard的工作环境方面有一些经验(足够多,因此,在3.8版本中发现的其中一个较模糊的错误是由于该经验而发现的)。这是一个非常好的分配器,但是对我们而言,要取决于工作量。为了在商业项目中使用它而不用GPL编写代码,我们必须支付Hoard的费用(尽管它并不算太贵)。

稍作修改的ptmalloc2一直是glibc的malloc后面的分配器,因此它得到了广泛使用和测试。如果最重要的是稳定性,那么它可能是一个不错的选择,但是我们没有在列表中提及它,因此我认为它已经解决了。对于某些工作负载,这很可怕,但是任何通用malloc都是如此。

如果我们愿意为此付费(根据我的经验,价格合理),SmartHeap SMP也是一个不错的选择。提到的大多数其他分配器都设计为可通过LD_PRELOAD插入的malloc / free新/删除替换。 SmartHeap也可以以这种方式使用,但它还包括一个与分配有关的完整API,可让我们根据自己的内情对分配器进行微调。在我们已经完成的测试中(同样,非常特定于特定的应用程序),SmartHeap在用作嵌入式malloc替代品时的性能与Hoard大致相同。两者之间真正的区别在于定制程度。我们不需要分配器的通用性就可以得到更好的性能。

根据用例,通用多线程分配器可能根本就不是我们想使用的分配器;而是我们可以使用它。如果我们不断地对大小相同的对象进行malloc和释放,则可能只想编写一个简单的slab分配器。 Slab分配在适合该描述的Linux内核中的多个位置使用。 (我会给我们几个有用的链接,但我是"新用户",Stack Overflow决定不允许新用户在一个答案中提供太多帮助。不过Google可以提供足够的帮助。)