std::map标准分配器与块分配器的性能比较

9
我在一本C++优化手册上读到,STL容器(如std::list、std::set、std::multi_set、std::map和std::multi_map)的标准分配器可以被更高效的块分配器替代。
块分配器具有更高的性能、低的碎片化和高效的数据缓存。
我在网上找到了FSBAllocator,它声称比标准分配器更快。 http://warp.povusers.org/FSBAllocator/ 我尝试使用它来处理std::map,发现确实比标准分配器更快。但我的问题是,为什么STL的实现会比特定的分配器慢那么多?采用其他分配器是否会影响可移植性和鲁棒性?我的代码必须能够在各种体系结构上编译(win32、osx、linux)。 是否有人使用过这种固定大小块分配器?

我假设STL分配器尽可能通用且对大多数情况都很有效率。 除非我的代码真的存在性能问题,否则我不会使用其他类型的分配器。 - Max
块分配器听起来似乎不能像标准分配器那样以尽可能少的开销分配任意大小的内存块。 - Mooing Duck
1个回答

13
A block allocator(块分配器)将进行一次大的自由存储/堆分配,然后内部将此内存分成块。这里的一个缺点是它直接分配了这个块(需要很大,并且通常是基于每个用例指定的),因此即使您没有使用所有内容,该内存也会被占用。其次,标准内存分配器是在new / delete之上构建的,而new / delete又经常在malloc / free之上构建。虽然我不记得malloc / free在所有情况下都保证线程安全,但它通常是这样的。
但最后一个原因是为什么块分配器效果如此出色,是因为它们具有标准分配器没有的信息,并且它们不需要覆盖非常广泛的用例。例如,如果您执行std :: map ()并且它分配了1mb,您可能会感到愤怒,但是如果您执行std :: map ,block_alloc <1024 * 1024 >>(),您将期望它。标准分配器不会分配块,它们通过new请求新内存,new根本没有任何上下文。它获得一个任意大小的内存请求,并需要找到连续的字节以返回。大多数实现都是通过维护一组不同倍数的内存区域来处理这个问题(例如,4个字节的区域更或多或少可以保证存在,因为对4个字节的请求非常普遍)。如果请求不是偶数倍,则很难返回一个好的块而不浪费空间并导致碎片化。基本上,如果要使任意大小的内存管理接近恒定时间、低碎片化、线程安全等,则非常非常难以实现。

Boost池分配器文档中提供了一些关于如何优化块分配器的好信息。


谢谢,解释得很好。我想我会继续使用默认的分配器!我相信STL的实现。 - linello

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接