【问题标题】:Ways to avoid memory fragmentation避免内存碎片的方法
【发布时间】:2013-03-28 17:33:43
【问题描述】:

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

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

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

【问题讨论】:

  • 给猫剥皮的方法有很多。但是,您的池分配器真的比默认的 new/delete 更好吗?
  • 实现自己的子分配器的程序员通常最终会成为乌普萨拉的朝圣者。对分配大小进行四舍五入可能是一个 Q&D 解决方法。
  • @Clifford,感谢更新。

标签: c++ memory-management rtos memory-fragmentation


【解决方案1】:

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

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

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

【讨论】:

  • 我同意。将你的池分成若干个桶,每个桶只分发固定大小的块。
【解决方案2】:

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

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

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

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

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

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

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 1970-01-01
      • 2011-01-05
      • 1970-01-01
      • 1970-01-01
      • 2013-08-14
      • 1970-01-01
      相关资源
      最近更新 更多