stats | 一个用来接收的统计数据数组,它按大小的 2 的幂对自由块进行分组。如果给定一个小的数组,则 Unity 会将较大的自由块算在最终数组元素中。 |
long 返回动态堆中的自由块的总数。
返回堆内存碎片信息。
堆碎片是衡量动态堆中潜在无法使用空间大小的一种方式。如果应用程序的堆碎片太多,会导致内存分配失败。
对于一次分配来说,可能存在比应用程序需要的更多的可用内存,但由于这种可用内存由两个或更多更小的独立内存块组成,因此分配可能会失败。
在运行时,某些内存使用模式会导致自由块的数量随时间推移而增加,导致堆出现碎片。
例如,考虑 Unity 释放大分配时,一个单独的大自由块会被返回到堆中。如果之后没有可用的较小块,则这个较大的自由块可用于满足更多较小的分配。
如果除这个块中的单个分配之外的其他所有小分配被释放掉,那么堆现在有两个较小的自由块,它们位于单个剩余分配的两侧。如果之后没有较大的块可供使用,则重新分配最初的较大空间可能会失败。
由于 Unity 会动态分配和释放内存,它通过跟踪空闲内存块来管理堆区域。在内部,Unity 将这些空闲内存块按类似大小分组 - 分组为 2 的幂大小,介于 2 的一个幂和下一个幂之间,具体为 [(2^n) .. (2^(n+1) - 1)]。
例如,块大小为 [1]、[2..3]、[4..7]、[8..15]、[16..31]、[32..63]、[64..127]、[128..256] ... 字节。
此设计无论分配大小或堆容量如何,都能为所有分配提供快速且恒定的时间分配器性能。
您可以使用 Profiler.GetTotalFragmentationInfo 跟踪堆的空闲内存块过去一段时间的情况。
using Unity.Collections; using UnityEngine; using UnityEngine.Profiling;
public class Example : MonoBehaviour { const int kFreeBlockPow2Buckets = 24;
void Update() { var freeStats = new NativeArray<int>(kFreeBlockPow2Buckets, Allocator.Temp); var freeBlocks = Profiler.GetTotalFragmentationInfo(freeStats);
Debug.Log(string.Format("Total Free Blocks: {0}", freeBlocks)); for (int i = 0; i < kFreeBlockPow2Buckets; i++) { Debug.Log(string.Format(" size[2^{0}] = {1} blocks", i, freeStats[i])); } } }