可遍历内存池的数据结构

Data structures for traversable memory pool

本文关键字:数据结构 内存 遍历      更新时间:2023-10-16

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

  • 分配的元素应该可以在线性时间中按其内存地址的顺序遍历,以促进缓存重用
  • 需要能够解除分配元素(内存块)并将它们返回到内存池

在实时程序运行期间,分配和释放会频繁发生,因此需要尽快发生。

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

我可以使用哪些数据结构来尽可能高效地进行分配我考虑使用红黑树(或类似的平衡BST)来存储分配的元素,并为空闲元素创建优先级队列。这将使分配和解除分配都为O(logn)。

关于如何改进这个设计,有什么建议吗?我可以使用的其他数据结构?是否有可能通过恒定的时间操作来创建一个内存池(具有上述限制)?

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

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

  • 通过池中的索引来识别每个内存块(block_address = base_address + index * block_size可以很容易地从该索引中导出内存块的地址,反之亦然)
  • 拥有元数据的数据结构(以跟踪已分配和空闲的块)。一个能满足需求的数组是一个固定大小的数组,其中有一个对应于每个内存块的项(由相同的索引标识)。该数组中嵌入了两个(双)链表(一个用于已分配块,一个用于空闲块)。由于这些链表不重叠,它们可以使用相同的prevnext指针

这如何符合要求:

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