了解内存池

时间:2017-05-30 04:52:54

标签: c++ performance optimization memory-management memory-pool

根据我的理解,内存池是一个块,或者在运行之前在堆栈上分配多个内存块 相比之下,根据我的理解,从操作系统请求动态内存,然后在运行时分配在堆上。

//编辑//

  • 内存池显然不一定分配在堆栈上,即。内存池可以与动态内存一起使用。
  • 根据此问题的答案,非动态内存显然未必在堆栈上分配。
  • '动态与静态内存' '内存池' 的主题因此并不真正相关虽然答案仍然相关。

据我所知,内存池的目的是提供RAM的手动管理,其中内存必须由程序员跟踪和重用。

由于多种原因,这在理论上对性能有利:

  1. 动态内存随时间变得分散
  2. CPU可以比动态块更快地解析静态内存块
  3. 当程序员控制内存时,根据具体程序,他们可以选择在最好的情况下释放和重建数据。
  4. 4.当多线程时,单独的池允许单独的线程独立运行而无需等待共享堆(Davislor)

    我对内存池的理解是否正确?如果是这样,为什么看起来内存池不经常使用?

3 个答案:

答案 0 :(得分:6)

XY problempremature optimisation似乎阻碍了这个问题。

您应该专注于编写易读代码,然后使用分析器在必要时执行优化

  

我对内存池的理解是否正确?

不完全。

  

......在堆栈上......

     

......在堆上......

存储持续时间与池的概念正交;可以将池分配为具有四个存储持续时间中的任何 (它们是:静态,线程,自动和动态存储持续时间)。

C ++标准并不要求中的任何进入堆栈;考虑所有这些可能是有用的,就像它们进入同一个地方一样......毕竟,它们(通常)都会进入硅芯片

  

...在运行时之前分配......

重要的是多个对象的分配在之前发生(或者至少不常见)首先使用这些对象;这节省了必须单独分配每个对象。我认为这是你在运行时"之前的意思。在选择分配的大小时,越接近任何给定时间所需的对象总数,过度分配所产生的浪费越少,过度调整大小的浪费就越少。

但是,如果您的操作系统不是史前的,那么池的优势将会迅速减少。如果您在进行优化之前和之后使用了分析器,您可能会看到这一点!

  
      
  1. 动态内存随时间变得分散
  2.   

对于像Windows 1.0这样的天真操作系统,情况可能如此。但是,在这个时代,具有分配存储持续时间的对象通常存储在虚拟内存中,它会定期写入磁盘并从磁盘读回(这称为 paging ) 。因此,碎片化的内存可以进行碎片整理,更常用的对象,函数和方法甚至可能最终被整合到常见的页面

也就是说, paging 为您形成一个隐含的 pool (以及缓存预测)!

  

CPU可以比动态块更快地解析静态内存块

虽然分配了静态存储持续时间的对象通常位于堆栈上的,但这并非C ++标准强制要求。完全有可能存在C ++实现,其中静态内存块在堆上分配,而不是。

动态对象上的缓存命中率与静态对象上的缓存命中速度一样快。只是因为堆栈通常保存在缓存中;您应该尝试在没有堆栈的情况下编写,并且您可能会发现缓存有更多空间来存储

在优化之前,您应始终使用分析器来衡量最重要的瓶颈!然后您应该执行优化,然后再次运行分析器以确保优化成功!

这不是与机器无关的过程!您需要优化 per-implementation 一个实现的优化可能是另一个悲观化

  

如果是这样,为什么内存池似乎不经常使用?

上面描述的虚拟内存抽象与使用缓存分析器消除猜测相结合,实际上消除了 pool 在除了最不明智之外的所有人的有用性(即< strong>使用分析器)方案。

答案 1 :(得分:2)

自定义分配器可以帮助提高性能,因为默认分配器针对特定用例进行了优化,这种情况很少分配大块内存。

但是,例如,在模拟器或游戏中,你可能会在一个帧中发生很多事情,非常频繁地分配和释放内存。在这种情况下,默认分配器不是那么好。

一个简单的解决方案是为帧中发生的所有一次性事件分配一块内存。可以一遍又一遍地重写该存储器块,并且可以将删除延迟到以后的时间。例如:游戏等级的结束或其他。

答案 2 :(得分:1)

内存池用于实现自定义分配器。

常用的是线性分配器。它只保持一个指针分隔/分配/空闲内存。与之分配只需将指针递增所请求的N个字节,并返回其先前的值。通过将指针重置为池的开头来完成释放。