避免内存碎片的方法

Ways to avoid memory fragmentation

本文关键字:方法 内存碎片      更新时间:2023-10-16

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

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

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

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

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

此方法将要求您的内存分配器在写入时考虑"固定大小"。

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

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

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

服务从一个池中短时分配大小为1到X字节,从另一个池中长时间分配大小为1到X字节。

对于大小为X +1到2X、2X +1到4X、4X +1到8X等的分配也是如此。(你可以尝试其他桶的大小…)

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

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

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

  • 垃圾收集不一定与实时需求不兼容。实时意味着"你的系统必须保证在一定期限内做出反应"。如果垃圾收集器以增量方式工作,并且能够保证足够短的"空出世界"阶段,那么就可以了。
  • 现代垃圾收集器的性能并不都很差。人们总是倾向于忘记freedelete也是非常昂贵的操作。
  • 垃圾收集是有权衡的:最有效的垃圾收集具有较长的空世界阶段。空相较短的总效率较低。

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