首页 > 解决方案 > 堆上的页面对齐内存分配是否有任何优化或不同的 API?

问题描述

我即将编写一个表示双端队列的类,就像 一样std::dequeue,但能够存储任何可破坏的类型,并且不支持索引。迭代或弹出操作只有在知道之前存储的类型时才会起作用。大多数情况下,它将用作队列/堆栈之类的存储,由其他类型引用,因为引用保证保持有效,即使它被推送/弹出到其间的任一端。内存的分配和释放应该在大块中完成。系统页面大小似乎非常适合默认块大小。

我认为,页面大小的内存块的页面对齐分配是有意义的,以减少迭代容器元素时的缓存未命中。这是真的?

恐怕使用std::aligned_alloc()with page alignment and size 会导致堆的元数据(例如,稍后需要free()知道分配的内存的大小)存储在分配的内存前面,这将导致巨大的浪费内存(每个分配的页面几乎一页)。或者对于堆的页面对齐内存分配是否有任何优化或不同的 API?例如,我可以想象一个 API 允许客户端指定存储所需元数据的位置,或者在分配时返回指向内存的指针和指向元数据的指针。

另一方面,使用系统原生 API(Windows / Posix / FreeRTOS)来分配页面将需要一个单独的内存池,这将是一个针对页面对齐内存分配进行优化的堆。但是有两个不知道彼此的堆也可能导致内存浪费,因为它们都有一个预先分配的页面池。还是大多数标准库实现一旦不再被客户端使用就将页面释放到操作系统?

标签: c++c++17heap-memorymemory-alignmentmemory-fragmentation

解决方案


对于缓存命中和未命中优化,页面对齐块对您没有多大帮助。在那个级别,您应该寻找高速缓存内存行对齐。在 x86 CPU 上将是 64 字节。

页面对齐可以帮助您优化从操作系统分配的 RAM 量。这取决于您的分配器一次从 new 或 malloc 中要求的块的大小。该领域的损失通常相当小,或为零。如果使用操作系统调用,请使用以下公式计算浪费的内存量:

(PAGE_SIZE - (BlockSize % PAGE_SIZE)) * BlockCount

为了获得最佳缓存优化,在缓存行边界上对齐各个元素,包括与列表相关的指针,对于 x86,再次对齐 64 字节。这是您将获得最大性能的地方。谨防!这也是内存中大部分浪费的来源。

该区域的内存浪费是

(LINE_SIZE - (ItemSize % LINE_SIZE)) * ItemCount

推荐阅读