内存池的初始块大小

Initial block size for memory pool

我正在使用 C++ 模板实现一个内存池 class,我想知道该块的合适大小是多少。例如:

template <typename T>
class Mempool {

  unsigned char* block;

  // constructor. 
  Mempool() {
    block = malloc(sizeof(T)*DEFAULT_N)
  }

};

在上面的例子中,块大小实际上取决于类型T和要创建的元素数量的默认值。执行此操作的最佳(或常见)做法是什么?我应该在这里考虑块大小的内存对齐吗?

我只能给出一些一般性建议,因为很多都取决于实际用例:

对齐方式: 我想池应该确保其中的对象正确对齐。这意味着您可能希望将对象放置在至少是 std::alignment_of<T>::valuealignof(T).

倍数的内存位置

缓存友好性:池也可能将对象位置四舍五入为缓存行大小的倍数,因此(小)对象永远不会跨两个缓存行放置但总是位于一个单独的。

Padding:如果对象非常小(只有几个字节)但你有很多,那么任何额外的填充都可能会增加内存需求,这取决于应用程序这是否会成为问题。当对象没有放在靠近的位置并且有很多缓存未命中时,太多的填充实际上可能会损害性能。

底层内存管理:最后,块大小也可能取决于底层存储。您可能希望您的分配大小与 OS 页面大小相匹配,或者使用它们的倍数。此外,如果 malloc 开销很大,那么您可能希望尽可能少地调用它以避免系统调用开销和争用。在 malloc 更便宜的环境中,使用较小的初始块大小和更频繁地使用 malloc 可能没问题,尽管 malloc 仍然会有 一些 高架。其中很大一部分是 OS 特定的。

因此,无论您选择初始大小,您都应该测量一些典型工作负载的内存使用情况和分配性能。这将使您能够做出比纯粹猜测所能提供的更有根据的估计。

最后,还有现成的 malloc 替代品,例如 tcmallocjemalloc,它们的特性可能与你的 OS 的 malloc。因此,一个不错的选择是检查其中之一,而不是滚动您自己的分配器。