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序列化哈希表及内存分配的主要内容,如果未能解决你的问题,请参考以下文章