【问题标题】:boost fast_pool_allocator sometimes requests a huge allocationboost fast_pool_allocator 有时会请求大量分配
【发布时间】:2026-01-29 17:50:01
【问题描述】:

我有一个高度线程化的应用程序,它在quickfix (1.13.3) 下使用 boost 的 fast_pool_allocator(版本 1.55)。该应用程序在一天中分配大量对象,或多或少呈线性增长,直到我们将其关闭,到一天结束时使用大约 32G 的虚拟内存。当我们观察应用程序的虚拟内存占用量增长时,大多数分配都在 200MB 左右。但随后,通常在当天晚些时候的某个时间点,boost 决定分配 6GB,即使通过应用程序的事务流没有发生重大变化。

查看分配器代码,boost 在分配后所做的第一件事是将新块设置为块。函数是simple_segregated_storage<SizeType>::segregate,位于 simple_segregated_storage.hpp:280。我们在进程中附加了一个调试器,并观察到当发生巨大分配时,该函数(不出所料)需要很长时间才能执行,特别是第 302 行的 for 循环。它需要长达 20-30 秒,并且该代码受互斥锁保护,因此所有其他线程都试图在分配器块中执行任何操作。这激怒了我们的客户。

问题:

  1. 在此之前一整天都在不断地请求约 200MB 块,为什么它会突然分配 6GB?
  2. 能否以某种方式限制分配?我宁愿让它更频繁地要小块。
  3. 这是错误的分配器吗?我想这是 quickfix 开发人员的问题,但这似乎是他们的首选方式。使用分配器的对象多为std::mapstd::multimap

【问题讨论】:

  • 因此,在阅读文档 10 分钟后,我发现了一个 MaxSize 参数,该参数似乎是对底层池一次分配多少“块”的限制,默认为 @ 987654326@(可能没有限制)。您是否检查过将MaxSize 设为非零值的影响?
  • 是的,就是这样。我会发布一个答案。谢谢。

标签: c++ memory-management boost quickfix boost-pool


【解决方案1】:

正如 Yakk 上面所建议的,事实证明,提升池确实允许您在模板中指定 MaxSize。有点奇怪,它以“块”为单位运行,这是池实现的内部概念。恕我直言,字节会更自然,但就这样吧。

fast_pool_allocator 使用所有模板参数(第一个除外)的默认值定义。我复制了这些默认值并更改了最后一个。对于这个应用程序,块大小为 88 字节,但我假设这取决于映射中的类。

typedef std::map <int, std::vector <FieldMap*>, std::less<int>, 
                  boost::fast_pool_allocator<std::pair<const int, std::vector<FieldMap*>>,
                                             boost::default_user_allocator_new_delete,
                                             boost::details::pool::default_mutex,
                                             32,       // NextSize (default from boost)
                                             1500000   // MaxSize, in 88 byte chunks.
                                            >> Groups;

在这种情况下,1500000 * 88 = 132M,这大约是我现在希望分配的大小。

【讨论】:

  • MaxSize 不是用来封顶的,它只是和下次向系统请求的块数有关。看到这个post
最近更新 更多