简体   繁体   English

避免内存碎片的方法

[英]Ways to avoid memory fragmentation

I allocate a big memory pool from RTOS (I already know my application memory requirement, it will not grow beyond a certain size).我从 RTOS 分配了一个大内存池(我已经知道我的应用程序内存需求,它不会增长超过一定大小)。 And then my application allocation requests are fulfilled from that pool.然后我的应用程序分配请求从该池中得到满足。

Recently I started facing a problem;最近我开始面临一个问题; allocation request were not being fulfilled even though memory was there (got integrated memory bench marking framework, which showed this), investigation reveals we are suffering from memory fragmentation.即使有内存,分配请求也没有得到满足(有集成的内存基准框架,显示了这一点),调查显示我们正遭受内存碎片的困扰。

My application is heavily dependent on STL (also receive data from network, XML parsing, image manipulation, saving it as PNG etc), and as heap memory allocation behind memory fragmentation (are there any other reasons?), What are best ways to avoid it?我的应用程序严重依赖 STL(还从网络接收数据、XML 解析、图像处理、将其保存为 PNG 等),以及作为内存碎片背后的堆内存分配(还有其他原因吗?),有什么最好的方法可以避免它?

The typical cause for memory fragmentation is that large memory blocks gets split into smaller and smaller chunks as the pool ages.内存碎片的典型原因是随着池的老化,大内存块被分成越来越小的块。 The simple way to avoid this is to have fixed sizes.避免这种情况的简单方法是使用固定尺寸。

This clearly doesn't solve the problem that use 18MB of storage for XML where each XML node is stored as a small string, and then trying to load a 4096 x 4096 x 8bit PNG (16MB), if your pool is 24MB, because the XML will split your memory into tiny bits, and then you need 16MB of contiguous memory.这显然不能解决使用 18MB 存储 XML 的问题,其中每个 XML 节点存储为一个小字符串,然后尝试加载 4096 x 4096 x 8 位 PNG (16MB),如果您的池是 24MB,因为XML 会将您的内存分成很小的部分,然后您需要 16MB 的连续内存。 But the "fixed sizes" will avoid an XML string of <aaa>b</aaa> taking up 4 bytes and 2 bytes of memory, thus making the memory completely useless for anything else ever being stored there, since no other object is 4 or 2 bytes long.但是“固定大小”将避免<aaa>b</aaa>的 XML 字符串占用 4 个字节和 2 个字节的内存,从而使内存对于存储在那里的任何其他内容完全无用,因为没有其他对象是 4或 2 个字节长。

This method will require that your memory allocator as such is being written to take "fixed sizes" into account.此方法将要求您编写内存分配器以将“固定大小”考虑在内。

The first step would be to see if the RTOS provides any mechanism for low-fragmentation heaps.第一步是查看 RTOS 是否为低碎片堆提供任何机制。

If not, see if someone else already implemented a low-fragmentation allocator.如果没有,看看其他人是否已经实现了低碎片分配器。 A related question (from the right side bar) suggests an example.一个相关的问题(来自右侧栏)提出了一个例子。

Third, if no other existing solution works, a solution would be to use multiple memory pools for allocations.第三,如果没有其他现有解决方案有效,则解决方案是使用多个内存池进行分配。

Service short lived allocations of size 1 to X bytes from one pool and long lived allocations of size 1 to X bytes from another.为来自一个池的大小为 1 到 X 字节的短期分配和来自另一个池的大小为 1 到 X 字节的长期分配提供服务。

Similar for allocations of size X + 1 to 2X, 2X +1 to 4X, 4X + 1 to 8X and so on.类似于大小 X + 1 到 2X、2X +1 到 4X、4X + 1 到 8X 等的分配。 (You may experiment with other bucket sizes...) (您可以尝试使用其他桶大小...)

To determine the best size for X you will need to profile your app and see the frequency of each allocation size.要确定 X 的最佳大小,您需要分析您的应用程序并查看每个分配大小的频率。

Make sure each bucket has enough space to fulfill the allocations :)确保每个桶都有足够的空间来完成分配:)

Hypothetically: Switch to garbage collection.假设:切换到垃圾收集。 You need a compacting garbage collector, one that is able to physically move around allocated data, else it won't help with fragmentation.您需要一个压缩垃圾收集器,它能够在物理上移动分配的数据,否则它无助于碎片化。

  • Garbage collection is not necessarily incompatible with real-time requirements.垃圾收集不一定与实时要求不兼容。 Real-time means "your system has to guarantee reaction within a certain deadline".实时意味着“您的系统必须保证在特定期限内做出反应”。 If the garbage collector works incrementally and can guarantee a sufficiently short "hold-the-world"-phase, you're fine.如果垃圾收集器以增量方式工作并且可以保证足够短的“hold-the-world”阶段,那就没问题了。
  • Performance of modern garbage collectors is not all bad.现代垃圾收集器的性能并不全是坏的。 People always tend to forget that free and delete are pretty expensive operations also.人们总是倾向于忘记freedelete也是非常昂贵的操作。
  • There are trade-offs with garbage collection: The most efficient ones have long hold-the-world-phases.垃圾收集有一些权衡:最有效的有很长的保持世界阶段。 The ones with short hold-the-world-phases have lower overall efficiency.保持世界阶段较短的那些具有较低的整体效率。

Unfortunately all this is hypothetical, as I currently don't know of any compacting, incremental garbage collector for C++.不幸的是,所有这些都是假设的,因为我目前不知道任何用于 C++ 的压缩、增量垃圾收集器。 Except maybe C++/CLI.除了 C++/CLI。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM