2013-04-06 96 views
2

我从RTOS中分配一个大的内存池(我已经知道我的应用程序内存要求,它不会超过一定的大小)。然后我的应用程序分配请求将从该池中完成。避免内存碎片的方法

最近我开始面临一个问题;即使内存在那里(得到集成的内存基准标记框架,显示了这一点),分配请求并没有得到满足,调查显示我们正在遭受内存碎片化。我的应用程序严重依赖于STL(也接收来自网络的数据,XML解析,图像处理,将其保存为PNG等),并作为内存碎片后面的堆内存分配(是否还有其他原因?),什么是最好的方法来避免它?

+0

皮肤有很多种方法让这只猫。但是,你的池分配器是否比默认的'new/delete'更好? – jxh 2013-04-06 08:19:43

+1

实现自己的子分配器的程序员通常最终会做出乌普萨拉朝圣。整理分配大小可能是Q&D修复。 – 2013-04-06 12:22:30

+0

@Clifford,感谢您的更新。 – Saqlain 2013-04-07 16:21:04

回答

2

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

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

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

+0

我同意。将您的游泳池分成多个桶,每个桶只分发固定大小的块。 – 2013-04-06 08:28:34

2

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

如果不是,请查看是否有其他人已经实施了低碎片分配器。 A related question(来自右侧栏)提供了一个示例。

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

服务将大小为1的短期分配分配给一个池中的X个字节,将大小为1的长期分配分配给另一个池中的X个字节。

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

要确定X的最佳尺寸,您需要对应用进行配置并查看每个分配尺寸的频率。

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

0

打趣:切换到垃圾收集。你需要一个压缩垃圾收集器,一个能够物理移动分配的数据,否则它不会帮助分片。

  • 垃圾收集不一定与实时要求不兼容。实时意味着“您的系统必须在一定的期限内保证反应”。如果垃圾收集器逐渐工作,并且可以保证足够短的“持有世界”阶段,那么你就很好。
  • 现代垃圾收集器的表现并不全是坏事。人们总是会忘记freedelete也是非常昂贵的操作。
  • 有垃圾收集的权衡:最有效的是长期持有的世界阶段。世界短暂阶段的整体效率较低。

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