3

我在 C++ 中有一个使用场景,我多次调用的函数会创建一些本地的、小但动态大小的向量。在分析我的程序后,我注意到在 std::vector::free() 中花费了过多的时间。这种问题的自然(C++ 式)解决方案似乎是将默认分配器切换到更适合我的使用场景的东西。特别是,在这里使用内存池策略似乎很有意义。然而,到目前为止, boost::pool_alloc 一直是个麻烦。我已经让它工作了,但是虽然在我的小但经常调用的函数(我们将调用该函数 f())中分配更快,但它会导致调用 f() 的函数在返回之前挂起非常很久了

然而更多的分析表明,所有的时间(在我厌倦等待之前的几十分钟)都花在了 pool_allocator::ordered_free() 上。我在一个简单的测试程序中重现了同样的行为(虽然不是那么极端),而且看起来,事实上,当大量构造的向量将它们的内存返回到单例池时,函数在返回之前会挂起很长时间.

如果有人知道避免这种行为的方法,或者知道另一个不会遇到这种问题的 C++ 池分配器,我将非常感激!

4

2 回答 2

0

根据您的问题,我认为

  • 这只是一个功能
  • 向量的大小是有限的(你说它很小)
  • 该函数不会被递归调用太频繁

如果是这种情况,请考虑使用堆栈分配的内存而不是动态分配的内存。您可以通过不使用向量而是使用std::array<>和一些大小指示符(如果存储的类型是可构造的)或一些固定大小和放置新的原始内存缓冲区来做到这一点,或者将后者包装到分配器类中以使用带有该分配器类的向量.

如果您的性能问题仅限于这么小的代码区域,我不会使用诸如 boost::pool 之类的通用内存管理工具,而是针对当前情况推出一些非常专业的工具。

于 2013-02-26T08:53:20.210 回答
0

我自己写过几次,一旦一切顺利,分配和释放都非常快。1. 按大小创建池映射。2. 每个池都有一个块的双向链表。3.每个块的前后都有额外的空间用于列表节点和所有者池引用、大小检查等 4.分配速度很快,因为您只需要查找大小>=您的块大小的第一个池并取消列出第一个条目。5. 重新分配很快,因为你在内存块中有一个指向池的指针,所以你所要做的就是重新列出它。6.你可以在启动时创建一堆空池。然后,在每个分配上,首先尝试从池中取消列表。如果失败,那么 malloc() 代替。当块被释放时,将其添加回池中而不是释放它。7.一旦您的应用程序稳定运行,所有分配都将直接来自池链接列表,而释放将直接回到那里......超级快。8. 当你的程序退出时,Free() 池中的所有内存。

于 2013-02-26T07:25:36.733 回答