UE4-Archive序列化哈希表及内存分配

Posted RapdoZoro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE4-Archive序列化哈希表及内存分配相关的知识,希望对你有一定的参考价值。

文章为本人学习虚幻4引擎源码所整理笔记,如有纰漏欢迎指正交流。

一、从Archive中序列化HashMap流程:

1.从BinaryArchive中对FMetalShaderMap序列化:    (MetalShaders.cpp)

2.分别对Format和TMap类型的HashMap序列化:    (MetalShaderTesources.h)

3.TMap继承自TSortableMapBase,TSortableMapBase继承自TMapBase:    (Map.h)

查看TMapBase从Archive序列化,为对Map.Pairs序列化:

Pairs为TMapBase成员变量,Pairs为TSet类型:

4.查看TSet从Archive序列化,对Set.Elements序列化:    (Set.h)

Elements为TSet成员变量,Elements为TSparseArray类型:

二、稀疏数组序列化时内存分配及空位内存:

5.查看TSparseArray从Archive序列化,

    1). 先序列化出Element数量;

    2).让执行了Array.Empty(Num),注意正是执行了这一句,Array的内存分配大小一开始就确定了,后续不会动态分配大小造成内存浪费;

    3).然后遍历数量,每次对Array执行AddUninitialized()方法(该方法分配并获取内存空间);

    4).Array执行AddUninitialized()方法时并未对新增element初始化,仅获得分配了的内存空间;通过placement new方法来对element在分配的内存空间上进行构造 :   (SparseArray.h)

placement new方法实现:

6.继续查看AddUninitialized()方法实现:

    1).稀疏数组分配内存空间时会根据Flag优先查看连续内存空间上目前是否存在未被分配的空余空间(来源为之前分配过后来被释放);

    2).如果存在,优先分配空余空间;否则进行扩容:   (SparseArray.h)

Data为TSparseArray成员变量,Pairs为TArray类型:

三、TArray-Slack及内存扩容时分配器分配大小计算规则:

7.查看TArray进行插入时扩容的具体执行(此时不对element进行构造函数执行):   (Array.h)

8.调用ResizeGrow()方法:

    1).先计算最大内存分配长度ArrayMax(CalculateSlackGrow),Slack即为重新分配内存时可添加元素的数量,即剩余内存(应该是和NumFreeIndeices一样),Shrink可以移除Slack;

    2).再根据ArrayMax重新进行内存分配(ResizeAllocation)

AllocatorInstance为TArray的ElementType类型成员变量:(ArrayNum + SlackNum = ArrayMax)

9.查看分配器CalculateSlackGrow具体怎样分配大小,注意这里只是计算要分配的内存空间大小,并未实际分配内存空间(实际分配在之后的ResizeAllocation中):  (ContainerAllocationPolicies.h)

对于Container:

如果NumElements小于NumInlineElements,则返回固定值NumInlineElements;

如果NumElements大于NumInlineElements,则SecondaryData执行CalculateSlackGrow

SecondaryData:

默认用的FDefaultAllocator,在堆上分配内存:

    1).最初会分配为4,即ArrayMax = 4,ArrayNum = 1, Slack = 3;

    2).之后ArrayMax增值为1.375*ArrayNum + 16;

 四、计算内存分配大小后的实际内存分配:

10.在TArray的ResizeGrow()方法中,

    1).先通过ArrayNum和ArrayMax计算内存扩容所需的大小,即新的ArrayMax,

    2).再根据新的ArrayMax及OldNum(插入新元素扩容前的ArrayNum)进行实际的内存分配。 (Array.h)

11.查看内联文件上内存分配Realloc方法的具体执行:     (FMemory.inl)

以上。

 

 

以上是关于UE4-Archive序列化哈希表及内存分配的主要内容,如果未能解决你的问题,请参考以下文章

UE4-Archive序列化哈希表及内存分配

Java集合哈希表及哈希函数的实现方式

哈希表及冲突的方法

没有动态分配的哈希表/映射实现

OpenSSL之内存用法

Linux程序:--OpenSSL库之相关数据结构和内存分配