2

通读The Apache Modules Book,我在第 3.4.3 部分遇到了这个主张:

“第二个好处是在大多数平台上,池分配比 malloc 更快!”

我意识到这是一个悬而未决的问题,但是……嗯,为什么?

4

2 回答 2

6

除了 Lars 关于局部性的观点之外,池分配只是一种与malloc.

malloc必须跟踪每个分配的块,能够单独释放块,处理空闲块碎片和合并,有一些策略来选择从几个空闲块中分配,等等。

这是通用分配器所必需的,但池通过让调用者静态地决定一些这种行为来避免所有这些复杂性(以及相关的空间和运行时开销)。

Apache 示例似乎只允许整个池释放(所以它就像一个竞技场分配器)。这意味着它不需要跟踪单个分配记录、它们的生命周期和零散的免费存储。它只需要跟踪一个(或多个)大块内存,并更新指向下一个未使用空间的指针。请注意,即使使用 分配这些大块malloc,此成本通常也会在许多池分配中分摊。

其他池类型可能仅限于相同大小(或类型)的对象,这进一步简化了它们;他们甚至可以以接近零的成本保持 LIFO 免费列表,从而允许按记录重新分配。

于 2012-08-15T11:47:06.893 回答
4

池分配策略可以通过两种方式带来更好的性能。在数据结构遍历与数据分配顺序匹配的应用程序中,池化策略可以暴露更多的规则步幅。

例如,考虑通过记录的链接列表进行搜索。每条记录由一个关键字段、一个数据字段和一个指向列表中下一条记录的下一个字段组成。连续访问 key 和 next 字段,直到找到匹配项。只有这样才能访问数据字段。如果存储在每个记录中的数据本身就是一个堆对象,更糟糕的是,数据从记录到下一个记录的大小不同,那么对工作集的空间局部性就会产生各种不良影响。即,不必要地从内存中获取数据,消耗宝贵的带宽。

此外,由于可变长度数据介入键和下一个字段之间,记录内的步幅以及跨连续记录的步幅将显得不规则。因此,不同对象类型的隔离可以提高空间局部性,并随之提高整体性能。

此外,由于池分配可能会暴露更多的常规步幅,因此简单的预取策略可以预测未来的引用并缩短它们的内存访问延迟。

于 2012-08-15T11:34:19.120 回答