我将要编写一个表示双端队列的类,就像std::dequeue
一样,但具有存储任何可破坏类型的能力,并且没有索引支持。迭代或弹出操作仅在知道之前存储的类型时才起作用。在大多数情况下,它将被用作队列/堆栈之类的存储,由其他类型引用,因为即使将引用推入/弹出到两端之间,引用也可以保证保持有效。分配和释放内存应该分块进行。系统页面大小似乎非常适合默认块大小。
我假设,页面大小的内存块的页面对齐分配是有意义的,以便减少容器元素迭代时的缓存丢失。 这是真的吗?
[恐怕将std::aligned_alloc()
与页面对齐和大小一起使用将导致堆的元数据(例如,free()
稍后需要,以了解分配的内存的大小)存储在分配的内存中,这将导致大量的内存浪费(每个分配的页面将近一页)。 或者对于堆的页面对齐的内存分配,是否有任何优化或其他API?例如,我可以想象一个API,它允许客户端指定在哪里存储所需的元数据,或者该API返回指向内存的指针以及指向分配时元数据的指针。
另一方面,使用系统本机API(Windows / Posix / FreeRTOS)分配页面将需要一个单独的内存池,这将是为针对页面对齐的内存分配而优化的堆。但是拥有两个不知道的堆也可能导致内存浪费,因为两个堆都有一个预分配的页面池。 或者大多数标准库实现是否在客户端不再使用它们后立即向操作系统释放页面?
对于高速缓存命中和遗失优化,页面对齐的块将无济于事。在该级别上,您应该查找缓存行对齐。在x86 CPU上为64字节。
页面对齐方式可以帮助您优化从操作系统分配的RAM数量。这取决于您的分配器一次要向new或malloc声明的块的大小。该区域的损失通常很小,平均为分配的块大小的1/2除以页面大小。
为了获得最佳的缓存优化,请在行边界上将individual元素(包括与列表相关的指针)对齐,对于x86,再次为64个字节。这是您将获得最大性能的地方。