9

我在 C++ 优化食谱上读到 STL 容器的标准分配器,例如 std::list、std::set、std::multi_set、std::map、e std::multi_map 可以被更高性能的块分配器

块分配器具有更高的性能、低碎片和高效的数据缓存。

我在网上找到了声称比标准更快的 FSBAllocator。 http://warp.povusers.org/FSBAllocator/

我已经用 std::map 进行了尝试,发现似乎确实更快,但我的问题是 STL 实现怎么会比特定分配器慢,以及另一个分配器比标准分配器的缺点是什么?便携性和鲁棒性?我的代码必须在各种架构(win32、osx、linux)上编译。有人对这种固定大小的块分配器有经验吗?

4

1 回答 1

13

块分配器对空闲存储/堆进行一次大分配,然后在内部将此内存拆分为块。这里的一个缺点是它直接分配了这个块(它需要很大,并且通常是用户在每个用例的基础上指定的),所以即使你不使用它,那个内存也会被占用。其次,标准内存分配器建立在 new/delete 之上,而后者又通常建立在 malloc/free 之上。虽然我不记得 malloc / free 是否保证在所有情况下都是线程安全的,但通常是这样。

但最后,块分配器工作得如此出色的原因是因为它们具有标准分配器所没有的信息,并且它们不需要涵盖非常广泛的用例集。例如,如果你这样做了std::map< int, int >(),它分配了 1mb,你可能会生气,但如果你这样做了std::map< int, int, std::less< int >, block_alloc< 1024 * 1024 > >()你会期待的。标准分配器不会在块中分配,它们通过 new 请求新内存,而 new 则根本没有上下文。它获取任意大小的内存请求,并且需要找到要返回的连续字节数。大多数实现所做的是它们有一组存储区域,它们维护不同的倍数(例如,4 字节的区域或多或少可能保证存在,因为对 4 字节的请求非常普遍)。如果请求不是偶数,则在不浪费空间并导致碎片的情况下返回一个好块变得更加困难。基本上,如果您希望它接近恒定时间、低碎片、线程安全等,那么任意大小的内存管理是非常非常困难的。

Boost pool allocator文档有一些关于一个好的块分配器如何工作的好信息。

于 2012-03-08T15:15:44.520 回答