阅读《游戏引擎架构》(五)
2016-12-26 本文已影响85人
mx乐乐
内存管理
游戏程序员总希望把代码变得更快。任何软件的效能,不仅受算法的选择和算法编码效率所支配,程序如何运用内存(RAM)也是重要因素。
以malloc( )或C++的全局new运算符进行动态内存分配,是非常慢的操作。要提升效能,最佳方法是尽量避免动态内存分配,不然也可利用自制的内存分配器来大大减低分配成本。
当然,任何游戏引擎都无法完全避免动态内存分配,所以多数游戏引擎会实现一个或多个定制分配器。
定制分配器能享有比操作系统分配器更优的性能特征,原因有二。第一,定制分配器从预分配的内存中完成分配请求(预分配的内存来自malloc( ) 、new,或声明为全局变量)。这样放,分配过程都在用户模式下执行,完全避免进入操作系统的上下文切换。第二,通过对定制分配器的使用模式做出多个假设,定制分配器便可以比通用的堆分配器高效的多。
1.基于堆栈的分配器
堆栈分配器是非常容易实现的。我们要分配一大块连续内存,可简单的使用malloc( ) 、new。另外安排一个指针指向堆栈的顶端,指针以下的内存是已分配的,指针以上的内存是未分配的。对于每个分配请求,仅需要把指针往上移动请求所需的字节数量。要释放最后分配的内存块,也只需要把指针向下移动该内存块的字节数量。
通常堆栈分配器的接口类型类似这样:
class StackAllocator
{
public:
// 堆栈标记:表示堆栈的当前顶端
// 用户只可以回滚至一个标记,而不是堆栈的任意位置
typedef U32 Marker;
// 给定总大小,构建一个堆栈分配器
explicit StackAllocator(U32 stackSize_bytes);
// 给定内存块大小,从堆栈 顶端分配一个新的内存块
void* alloc(U32 size_bytes);
// 取得指向当前堆栈顶端的标记
Marker getMarker();
// 把堆栈回滚至之前的标记
void freeToMarker(Marker marker);
// 清空整个堆栈(把堆栈归零)
void clear();
private:
// .......
};```
![向堆栈分配,以及释放至一个标记](https://img.haomeiwen.com/i915770/db206971d4740170.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
未完待续......