我从 RTOS 分配了一个大内存池(我已经知道我的应用程序内存需求,它不会超过一定大小)。然后我的应用程序分配请求从该池中得到满足。
最近我开始面临一个问题;即使内存在那里,分配请求也没有得到满足(有集成的内存基准标记框架,这表明了这一点),调查显示我们正遭受内存碎片的困扰。
我的应用程序严重依赖 STL(也从网络接收数据、XML 解析、图像处理、将其保存为 PNG 等),以及作为内存碎片背后的堆内存分配(还有其他原因吗?),有什么最好的方法来避免它?
我从 RTOS 分配了一个大内存池(我已经知道我的应用程序内存需求,它不会超过一定大小)。然后我的应用程序分配请求从该池中得到满足。
最近我开始面临一个问题;即使内存在那里,分配请求也没有得到满足(有集成的内存基准标记框架,这表明了这一点),调查显示我们正遭受内存碎片的困扰。
我的应用程序严重依赖 STL(也从网络接收数据、XML 解析、图像处理、将其保存为 PNG 等),以及作为内存碎片背后的堆内存分配(还有其他原因吗?),有什么最好的方法来避免它?
内存碎片的典型原因是随着池的老化,大内存块被分成越来越小的块。避免这种情况的简单方法是固定大小。
这显然不能解决使用 18MB 存储 XML 的问题,其中每个 XML 节点存储为一个小字符串,然后尝试加载 4096 x 4096 x 8bit PNG (16MB),如果您的池是 24MB,因为XML 会将您的内存分成小块,然后您需要 16MB 的连续内存。但是“固定大小”将避免<aaa>b</aaa>
占用 4 字节和 2 字节内存的 XML 字符串,从而使内存对于存储在那里的任何其他内容完全无用,因为没有其他对象是 4 或 2 字节长。
此方法将要求您的内存分配器被写入以考虑“固定大小”。
第一步是查看 RTOS 是否为低碎片堆提供任何机制。
如果没有,看看其他人是否已经实现了低碎片分配器。一个相关问题(来自右侧栏)提出了一个示例。
第三,如果没有其他现有的解决方案有效,一个解决方案是使用多个内存池进行分配。
服务来自一个池的大小为 1 到 X 字节的短期分配,以及来自另一个池的大小为 1 到 X 字节的长期分配。
大小 X + 1 到 2X、2X +1 到 4X、4X + 1 到 8X 等的分配类似。(您可以尝试其他大小的桶......)
要确定 X 的最佳大小,您需要分析您的应用程序并查看每个分配大小的频率。
确保每个桶有足够的空间来完成分配:)
假设:切换到垃圾收集。您需要一个压缩垃圾收集器,它能够在物理上移动分配的数据,否则它对碎片没有帮助。
free
,而且delete
操作也非常昂贵。不幸的是,所有这些都是假设的,因为我目前不知道任何用于 C++ 的压缩增量垃圾收集器。除了 C++/CLI。