我有一个 Visual Studio 2008 C++ 应用程序,我在其中使用标准容器的自定义分配器,以便它们的内存来自内存映射文件而不是堆。此分配器用于 4 个不同的用例:
- 104字节固定大小结构
std::vector< SomeType, MyAllocator< SomeType > > foo;
- 200字节固定大小结构
- 304字节固定大小结构
- n 字节字符串
std::basic_string< char, std::char_traits< char >, MyAllocator< char > > strn;
我需要能够为每一个分配大约 32MB 的空间。
std::map
分配器使用指向分配大小的指针来跟踪内存使用情况。typedef std::map< void*, size_t > SuperBlock;
每个 SuperBlock 代表 4MB 内存。
std::vector< SuperBlock >
如果一个 SuperBlock 没有足够的空间,则有一个。
分配器使用的算法如下:
- 对于每个超级块:超级块的末端是否有空间?把分配放在那里。(快速地)
- 如果没有,则在每个 SuperBlock 中搜索足够大小的空白空间并将分配放在那里。(减缓)
- 依然没有?分配另一个 SuperBlock 并将分配放在新 SuperBlock 的开头。
不幸的是,第 2 步可能会在一段时间后变得非常缓慢。随着对象的复制和临时变量的销毁,我得到了很多碎片。这会导致在内存结构中进行大量深度搜索。碎片化存在问题,因为我可以使用的内存有限(请参阅下面的注释)
任何人都可以建议改进这个算法来加快这个过程吗?我是否需要两种单独的算法(一种用于固定大小的分配,一种用于字符串分配器)?
注意:对于那些需要理由的人:我在 Windows Mobile 中使用此算法,其中堆有 32MB 的进程槽限制。所以,通常std::allocator
不会削减它。我需要将分配放在 1GB 大内存区域中以获得足够的空间,这就是这样做的。