内存池的初始块大小
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>::value
或 alignof(T)
.
倍数的内存位置
缓存友好性:池也可能将对象位置四舍五入为缓存行大小的倍数,因此(小)对象永远不会跨两个缓存行放置但总是位于一个单独的。
Padding:如果对象非常小(只有几个字节)但你有很多,那么任何额外的填充都可能会增加内存需求,这取决于应用程序这是否会成为问题。当对象没有放在靠近的位置并且有很多缓存未命中时,太多的填充实际上可能会损害性能。
底层内存管理:最后,好块大小也可能取决于底层存储。您可能希望您的分配大小与 OS 页面大小相匹配,或者使用它们的倍数。此外,如果 malloc
开销很大,那么您可能希望尽可能少地调用它以避免系统调用开销和争用。在 malloc
更便宜的环境中,使用较小的初始块大小和更频繁地使用 malloc
可能没问题,尽管 malloc
仍然会有 一些 高架。其中很大一部分是 OS 特定的。
因此,无论您选择初始大小,您都应该测量一些典型工作负载的内存使用情况和分配性能。这将使您能够做出比纯粹猜测所能提供的更有根据的估计。
最后,还有现成的 malloc 替代品,例如 tcmalloc、jemalloc,它们的特性可能与你的 OS 的 malloc
。因此,一个不错的选择是检查其中之一,而不是滚动您自己的分配器。
我正在使用 C++ 模板实现一个内存池 class,我想知道该块的合适大小是多少。例如:
template <typename T>
class Mempool {
unsigned char* block;
// constructor.
Mempool() {
block = malloc(sizeof(T)*DEFAULT_N)
}
};
在上面的例子中,块大小实际上取决于类型T
和要创建的元素数量的默认值。执行此操作的最佳(或常见)做法是什么?我应该在这里考虑块大小的内存对齐吗?
我只能给出一些一般性建议,因为很多都取决于实际用例:
对齐方式:
我想池应该确保其中的对象正确对齐。这意味着您可能希望将对象放置在至少是 std::alignment_of<T>::value
或 alignof(T)
.
缓存友好性:池也可能将对象位置四舍五入为缓存行大小的倍数,因此(小)对象永远不会跨两个缓存行放置但总是位于一个单独的。
Padding:如果对象非常小(只有几个字节)但你有很多,那么任何额外的填充都可能会增加内存需求,这取决于应用程序这是否会成为问题。当对象没有放在靠近的位置并且有很多缓存未命中时,太多的填充实际上可能会损害性能。
底层内存管理:最后,好块大小也可能取决于底层存储。您可能希望您的分配大小与 OS 页面大小相匹配,或者使用它们的倍数。此外,如果 malloc
开销很大,那么您可能希望尽可能少地调用它以避免系统调用开销和争用。在 malloc
更便宜的环境中,使用较小的初始块大小和更频繁地使用 malloc
可能没问题,尽管 malloc
仍然会有 一些 高架。其中很大一部分是 OS 特定的。
因此,无论您选择初始大小,您都应该测量一些典型工作负载的内存使用情况和分配性能。这将使您能够做出比纯粹猜测所能提供的更有根据的估计。
最后,还有现成的 malloc 替代品,例如 tcmalloc、jemalloc,它们的特性可能与你的 OS 的 malloc
。因此,一个不错的选择是检查其中之一,而不是滚动您自己的分配器。