我在一本 C++ 优化手册上读到,STL 容器的标准分配器,如 std::list、std::set、std::multi_set、std::map、e std::multi_map 可以替换为性能更高的 block 分配器。
block 分配器具有更高的性能、低碎片和高效的数据缓存。
我在网上找到了 FSBAllocator,它声称比标准速度更快。 http://warp.povusers.org/FSBAllocator/
我已经用 std::map 试过了,发现它确实更快,但我的问题是 STL 实现怎么会比特定分配器慢那么多,而另一个分配器比标准分配器有什么缺点,在便携性和稳健性方面?我的代码必须在各种体系结构(win32、osx、linux)上编译。 有人使用过那种固定大小的 block 分配器吗?
最佳答案
block 分配器对空闲存储/堆进行大量分配,然后在内部将此内存拆分为 block 。这里的一个缺点是它直接分配了这个 block (它需要很大,并且通常是用户在每个用例的基础上指定的),所以即使你不使用所有它,内存也会被占用。其次,标准内存分配器建立在 new/delete 之上,而后者通常建立在 malloc/free 之上。虽然我不记得 malloc/free 是否保证在所有情况下都是线程安全的,但通常是这样。
但最后, block 分配器工作如此出色的原因是因为它们具有标准分配器不存在的信息,并且它们不需要涵盖非常广泛的用例集。例如,如果你做了 std::map< int, int >()
它分配了 1mb 你可能会生气,但如果你这样做 std::map< int, int, std::less< int >, block_alloc< 1024 * 1024 > >()
你会期待它。标准分配器不会按 block 分配,它们通过 new 请求新内存,而 new 又根本没有上下文。它得到一个任意大小的内存请求,需要找到一个连续的字节数来返回。大多数实现所做的是它们有一组内存区域,它们维护不同倍数(例如,一个 4 字节的区域或多或少可能保证存在,因为对 4 字节的请求非常常见)。如果一个请求不是偶数倍数,那么在不浪费空间和导致碎片的情况下返回一个好的 block 会变得更加困难。如果您希望它接近恒定时间、低碎片、线程安全等,那么基本上任意大小的内存管理都很难做到。
Boost pool allocator文档中有一些关于好的 block 分配器如何工作的有用信息。
关于c++ - std::map 标准分配器性能与 block 分配器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9619488/