C++ 可遍历内存池的数据结构

C++ 可遍历内存池的数据结构,c++,memory,memory-management,data-structures,C++,Memory,Memory Management,Data Structures,我在C++中实现内存池,有以下约束: 分配的元素应按其内存地址的线性时间顺序进行遍历,以促进缓存重用 需要能够释放元素(内存块)并将它们返回到内存池 分配和解除分配在实时程序运行期间会频繁发生,因此需要尽可能快地发生 到目前为止,我已经使用两个链表作为存根实现了这个内存池,一个用于空闲,另一个用于分配的元素。这是可行的,但速度当然非常慢,因为每次释放或分配元素时,都需要从一个列表中删除该元素并将其添加到另一个列表中,这是线性的。我希望这能更快 我可以使用什么数据结构来尽可能有效地(取消)分配

我在C++中实现内存池,有以下约束:

  • 分配的元素应按其内存地址的线性时间顺序进行遍历,以促进缓存重用
  • 需要能够释放元素(内存块)并将它们返回到内存池
分配和解除分配在实时程序运行期间会频繁发生,因此需要尽可能快地发生

到目前为止,我已经使用两个链表作为存根实现了这个内存池,一个用于空闲,另一个用于分配的元素。这是可行的,但速度当然非常慢,因为每次释放或分配元素时,都需要从一个列表中删除该元素并将其添加到另一个列表中,这是线性的。我希望这能更快

我可以使用什么数据结构来尽可能有效地(取消)分配?我正在考虑使用红黑树(或类似的平衡BST)来存储分配的元素,并使用优先级队列来存储空闲元素。这将使分配和解除分配都是O(log n)

关于如何改进这个设计有什么建议吗?我可以使用的其他数据结构?甚至可以使用固定时间操作创建内存池(具有上述约束)


编辑:我应该澄清,这些数据结构仅用于存储和访问内存地址,内存块本身已分配且连续。

由于我们处理的是具有固定大小内存块的内存池,因此可以实现如下恒定时间操作:

  • 通过内存块在池中的索引来标识每个内存块(内存块的地址可以通过
    块地址=基地址+索引*块大小
    从该索引轻松导出,反之亦然)
  • 具有元数据的数据结构(以跟踪已分配和空闲的块)。一个符合需求的是一个固定大小的数组,其中一个项对应于每个内存块(由相同的索引标识)。该数组中嵌入了两个(双重)链表(一个用于分配的块,一个用于空闲块)。由于这些链表不重叠,它们可以使用相同的
    prev
    next
    指针
这如何符合要求:

  • 线性时间遍历:内存块可以通过其索引(在这种情况下,作为元数据一部分的空闲/分配标志可能很有用)或通过两个链表中的任何一个进行遍历,具体取决于需要。对数组和链表的迭代是在线性时间内完成的
  • 恒定时间分配:分配内存块意味着从空闲列表中获取第一个项目,并将其移动到分配的列表中(例如在末尾)。删除链表的第一项,以及将一项附加到链表的末尾都是固定时间操作(假设保留指向链表开始和/或结束的指针-使链表循环会有所帮助)。然后返回块的索引/地址
  • 恒定时间解除分配:解除分配内存块意味着通过其索引标识相应的元数据项,并将其从分配列表移动到空闲列表中(例如,在末尾)。从数组中通过索引获取项、从(双重)链接列表中删除给定项以及将项追加到链接列表的末尾都是固定时间操作

内存池通常处理固定大小的内存块。你也是这样吗?如果是这样的话,恒定时间操作绝对是可能的。是的,内存块的大小是固定的:)你能详细说明恒定时间操作吗,给定约束条件(可遍历和可释放)?天哪;很难相信遍历链表的速度会明显变慢。它有多大?您已经说过列表只包含指针,内存是否可用,所以我不确定您将释放什么。我假设所有的内存块都是在启动时分配的,所以当您从一个列表中删除一个地址时,您只是简单地指示它是正在使用还是空闲。为什么不使用一个带有某种空闲指示符的地址列表,这样就不会在两个列表之间来回移动地址呢?如果在一个大于100个元素的池中,每(取消)一次分配一次,遍历就会变得很明显,相当快就超过了常规内存分配/空闲的成本。通常使用带有空闲地址的单一列表。问题是我希望能够遍历已使用(非自由)的项。由于通常只使用了很小比例的内存池,因此完全遍历内存池似乎是浪费。在这种情况下,解除分配用于调用内存块中对象的析构函数,并从外部将该块排除在遍历之外。诸如lower_bound之类的算法可用于任何正向迭代器,因此如果地址保持排序,则可以节省一点时间。更好的做法是只列出一个结构列表,其中每个结构都有地址和一个免费指示符。然后写一个谓词来找到第一个空闲的。谢谢你的回答,非常清楚的解释:)我认为这很有效,但它打破了在使用链表进行遍历时按内存地址顺序遍历块的限制。当分配的块分散在阵列上时,简单地遍历整个阵列会出现一些非常糟糕的最坏情况(仍然是线性的,但是相对于分配的块的数量)。理想情况下,我会对两个链表进行排序,但我能想到的方法太昂贵了。因此,我的想法可能是使用红黑树和优先级队列来存储t