前言
作为一款超重量级的游戏引擎,Unreal Engine在提升效率和效果方面做了全面的尝试,内存池这种关乎效率的关键基础设施也不例外。为最大化的适应自己的特点,UE针对内存池做足了探索和优化。
总体而言,UE4的内存统一由FMemory来管理,但其内存分配策略确有多种方式。下表中罗列了UE4中的内存分配器。
序号 | 分配器 | 描述 |
---|---|---|
1 | Ansi | 默认使用的c语言分配器 |
2 | Stomp | check for memory stomping |
3 | TBB | Intel TBB, default for Windows |
4 | Jemalloc | FreeBSD malloc |
5 | malloc | Linux默认 |
6 | Binned | 一代装箱式内存分配器 |
7 | Binned2 | 二代装箱内存分配器 |
8 | Binned3 | 三代装箱内存分配器 |
9 | Platform | 平台自定义 |
上述分配器体现在枚举EMemoryAllocatorToUse中,如下:
enum EMemoryAllocatorToUse
{
Ansi,
Stomp,
TBB,
Jemalloc,
malloc,
Binned,
Binned2,
Binned3,
Platform,
};
上述9种分配器中,Binned1/2/3显然是Unreal自己设计开发的,笔者曾在嵌入式Linux(非Android)平台上使用过Unreal,其时采用的正式Binned2分配器。
因此本文首先从Binned系列的分配器开始讲起。
Binned分配器介绍
得名原因
Binned得名于Bin,主要有两个含义:
存储容器:"bin"可以指一个用于存放物品的容器,比如垃圾桶或者储物箱。这是"bin"最常见的含义之一,指的是一个可以存放、分类或暂时保存物品的空间
。
分组或分类:在数据处理和统计学领域,“bin"也可以指将数据分组到特定的类别或区间的过程。例如,在进行频率分布分析时,数据点会被"binned”(分组)到不同的区间或箱子中,以便于分析和解释数据
于我们而言,两个含义没有什么大不同,Binned我们大可以就叫做分箱式内存分配,或者分组式内存分配。
在Binned一代中,内存分配器只管理小块内存,大块内存直接扔给OS去处理。而一代中,小块内存正是采用预分配从16B到32K一系列大小不等的bin的方法,在申请时直接找出刚好够用的bin,从这个bin的Pool中一个Block分出去。
当然,上述的描述并不严谨,比如某个大小的bin的Pool并不仅有一个,分完了就没了。