设计和编码非碎片化的静态内存池

时间:2010-10-13 12:07:32

标签: c++ c stl fragmentation memory-pool

我之前听过这个词,我想知道如何设计和编码 如果可用,我应该使用STL分配器吗? 如何在没有操作系统的设备上完成? 使用它和使用常规编译器实现malloc / new之间的权衡是什么?

2 个答案:

答案 0 :(得分:3)

我建议您在花费大量精力编写自己的内存之前,应该知道需要一个非分段内存分配器。 std库提供的那个通常就足够了。

如果你需要一个,减少碎片的一般想法是一次性获取大块内存并从池中分配而不是要求操作系统偶尔为堆内存提供堆内存并且在堆中的高度变化的位置并散布与许多其他不同大小的物体。由于专用内存分配器的作者对从池中分配的对象的大小以及这些分配的发生方式有了更多了解,因此分配器可以比通用分配器(例如STL提供的分配器)更有效地使用内存。 / p>

您可以查看内存分配器(如Hoard),它们在减少内存碎片的同时,还可以通过提供可减少争用的线程特定堆来提高性能。这可以帮助您的应用程序更加线性地扩展,尤其是在多核平台上。

可以找到有关多线程分配器的更多信息here

答案 1 :(得分:2)

将尝试描述什么本质上是一个内存池 - 我只是在我的头顶打字,已经有一段时间了,因为我已经实现了一个,如果有些东西显然是愚蠢的,那只是一个建议! :)

1。 要减少碎片,您需要创建一个特定于您在其中分配的对象类型的内存池。实际上,您可以将每个分配的大小限制为您感兴趣的对象的大小。您可以实现一个模板化的类,其中包含动态分配的块列表(列表的原因是您可以增加空间量可用)。每个动态分配的块基本上都是T的数组。

然后你会有一个“免费”列表,它是一个单链表,其中头指向下一个可用块。然后分配只是返回头部。您可以在块本身中覆盖链接列表,即每个“块”(表示T的对齐大小),基本上是T和链接列表中的节点的并集,在分配时,它是T,当被释放时,列表中的节点。 !!有明显的危险!!或者,您可以分配一个单独的(和受保护的块,这会增加更多开销)来保存块中的地址数组。

分配是微不足道的,遍历块列表并从第一个可用分配,释放也是微不足道的,您需要做的额外检查是找到分配它的块,然后更新头指针。 (注意,您需要使用新的展示位置或覆盖T中的运算符new / delete - 有解决方法,google是您的朋友)

我认为“静态”意味着T类型的所有对象都有一个单例内存池。缺点是对于每个T,你必须有一个单独的内存池。您可能很聪明,并且拥有一个管理不同大小池的单个对象(例如,使用指向池对象的指针数组,其中索引是对象的大小)。

上一段的重点是要详细说明这是多么复杂,并且像RC上面说的那样,确保在你做之前需要它 - 因为它可能会引入比可能更多的痛苦!

2。 如果STL分配器满足您的需求,请使用它,它由一些非常聪明的人设计,他们知道他们在做什么 - 但是它适用于通用情况,如果您知道如何分配对象,则可以使上述执行速度更快。

3。 你需要能够以某种方式分配内存(硬件支持或某种HAL - 无论如何) - 否则我不确定你的程序将如何工作?

4。 常规的malloc / new做了很多东西(google是你的朋友,我的答案已经是一篇文章!)我上面描述的简单分配器不是可重入的,当然你可以用互斥量包装它提供一点掩护,即使这样,我也会担心简单的分配器比普通的malloc / free快几个数量级。

但如果您处于优化的这个阶段 - 可能您已经用尽了优化算法和数据结构使用的可能性?