2

我从 RTOS 分配了一个大内存池(我已经知道我的应用程序内存需求,它不会超过一定大小)。然后我的应用程序分配请求从该池中得到满足。

最近我开始面临一个问题;即使内存在那里,分配请求也没有得到满足(有集成的内存基准标记框架,这表明了这一点),调查显示我们正遭受内存碎片的困扰。

我的应用程序严重依赖 STL(也从网络接收数据、XML 解析、图像处理、将其保存为 PNG 等),以及作为内存碎片背后的堆内存分配(还有其他原因吗?),有什么最好的方法来避免它?

4

3 回答 3

4

内存碎片的典型原因是随着池的老化,大内存块被分成越来越小的块。避免这种情况的简单方法是固定大小。

这显然不能解决使用 18MB 存储 XML 的问题,其中每个 XML 节点存储为一个小字符串,然后尝试加载 4096 x 4096 x 8bit PNG (16MB),如果您的池是 24MB,因为XML 会将您的内存分成小块,然后您需要 16MB 的连续内存。但是“固定大小”将避免<aaa>b</aaa>占用 4 字节和 2 字节内存的 XML 字符串,从而使内存对于存储在那里的任何其他内容完全无用,因为没有其他对象是 4 或 2 字节长。

此方法将要求您的内存分配器被写入以考虑“固定大小”。

于 2013-04-06T08:19:58.187 回答
2

第一步是查看 RTOS 是否为低碎片堆提供任何机制。

如果没有,看看其他人是否已经实现了低碎片分配器。一个相关问题(来自右侧栏)提出了一个示例。

第三,如果没有其他现有的解决方案有效,一个解决方案是使用多个内存池进行分配。

服务来自一个池的大小为 1 到 X 字节的短期分配,以及来自另一个池的大小为 1 到 X 字节的长期分配。

大小 X + 1 到 2X、2X +1 到 4X、4X + 1 到 8X 等的分配类似。(您可以尝试其他大小的桶......)

要确定 X 的最佳大小,您需要分析您的应用程序并查看每个分配大小的频率。

确保每个桶有足够的空间来完成分配:)

于 2013-04-06T08:34:56.417 回答
0

假设:切换到垃圾收集。您需要一个压缩垃圾收集器,它能够在物理上移动分配的数据,否则它对碎片没有帮助。

  • 垃圾收集不一定与实时要求不兼容。实时意味着“您的系统必须保证在一定期限内做出反应”。如果垃圾收集器以增量方式工作并且可以保证足够短的“hold-the-world”阶段,那就没问题了。
  • 现代垃圾收集器的性能并不全是坏的。人们总是倾向于忘记这一点free,而且delete操作也非常昂贵。
  • 垃圾收集需要权衡取舍:最有效的垃圾收集时间较长。持有世界阶段较短的那些整体效率较低。

不幸的是,所有这些都是假设的,因为我目前不知道任何用于 C++ 的压缩增量垃圾收集器。除了 C++/CLI。

于 2013-04-06T08:54:14.203 回答