游戏设计模式——内存池管理

对C++游戏程序员来说,内存管理是一件相当头疼的问题。因为C++是将内存赤裸裸的交给程序员,而不像Java/C#有gc机制。

好处是这样对于高性能要求的游戏程序,原生的内存分配可以避免gc机制的臃肿操作,从而大大提高性能。

坏处是C++程序员得时时警惕内存问题:

内存泄露问题

do{
 T* object = new T();
}while(0);

上面的例子中。忘记回收内存,函数退栈导致丢失了object指针,就再也找回不了new的内存地址,这时内存一直就会被占用着。

内存泄漏很容易理解,不作多讲。

内存碎片问题

由于对堆内存的分配/释放的顺序是随机的,导致申请的内存块随机分布于原始内存,倘若分布不是连续的(随机顺序往往导致多个内存块都是相隔开的),那么便会产生“洞”。

游戏设计模式——内存池管理

随着时间推移,堆内存越来越多出现这些“洞”,导致可用的自由内存块被拆分成多个小内存块。

这就导致即使有足够的自由内存,分配请求仍然可能会失败。

游戏设计模式——内存池管理

内存页切换问题

虚拟内存系统把不连续的物理内存块(即内存页)映射至虚拟地址空间,使内存页对于应用程序来说看上去是连续的。

在支持虚拟内存的操作系统上,多次使用原生C/C++内存分配,有可能其中几次是一个内存页,几次是第二个内存页,又有几次是第三个内存页的内容....在重复共同使用这些内存的时候有可能导致昂贵的切换内存页开销。

一些本世代游戏机虽然技术上支持虚拟内存,但由于其导致的开销,多数游戏引擎不会使用虚拟内存。

游戏设计模式——内存池管理

内存池(Memory Pool)

对C++内存分配进行适合当前程序的封装就显得尤为重要,这样C++程序员就能在封装完内存机制后减少大量心思警惕内存问题。

而如何封装还能高效的使用内存,就成了一门学问——内存池管理。

而内存池是什么:

预先通过new或者malloc(原生的内存分配函数)分配好一个大块内存(挖好池子),然后提供这块内存池的再分配函数。

当程序员需要分配小块堆内存时,可以向这个内存池请求分配小内存。

  • 由于内存池本身往往内存比较大,所以内存池本身的分配释放不易产生内存碎片。
  • 即使程序员由于操作失误导致内存池内部出现内存碎片或者内存泄漏问题,但是整个内存池本身只要正确释放,内存问题就不会向外扩张。
  • 一次性分配好大内存,尽可能减少了多次分配可能导致的过多物理内存页,从而减少了切换内存页开销。

关注小编,更多IT技术第一时间奉上!

游戏设计模式——内存池管理


分享到:


相關文章: