Version: Unity 6.0 (6000.0)
语言 : 中文
动态堆分配器
线程局部存储 (TLS) 堆栈分配器

存储桶分配器

存储桶分配器是一种执行小型分配的快速无锁分配器。通常情况下,存储桶分配器是加快小型分配的第一步,然后分配再进入堆分配器。

分配器为分配保留内存块。每个内存块分为 16KB 的子部分。该过程不可配置,不会出现在用户界面中。每个子部分都分为分配。分配大小是配置的固定大小的倍数,称为粒度

配置示例

以下配置示例演示了为分配保留内存块的过程:

Windows、Mac 和 Linux 播放器的共享存储桶分配器
Windows、Mac 和 Linux 播放器的共享存储桶分配器

在此设置中,总内存块大小(存储桶分配器内存块大小 (Bucket Allocator Block Size))为 4MB,分配粒度(存储桶分配器粒度 (Bucket Allocator Granularity))为 16B。第一个分配为 16B,第二个分配为 32B (2*16),之后依次为 48B、64B、80B、96B、112B 和 128B,共计八个存储桶(存储桶分配器存储桶数量 (Bucket Allocator BucketCount))。

每个子部分包含不同数量的存储桶。要计算子部分中的存储桶数量,请将子部分大小 (16KB) 除以粒度大小。例如:

  • 当分配粒度为 64B 时,一个子部分可容纳 256 个存储桶。
  • 当分配粒度为 16B 时,一个子部分可容纳 1,024 个存储桶。

开发和发布构建比较

因为在开发构建中,每个分配都有一个额外的 40B 标头,所以存储桶分配器为开发构建和发布构建生成不同的使用情况报告。下图显示了 16B 和 64B 分配的开发构建和发布构建之间的区别:

开发构建和发布构建比较
开发构建和发布构建比较

因为标头的原因,分配器会在仅分配 4MB 中的 2MB 后报告已满:

[ALLOC_BUCKET]
      Large Block size 4.0 MB
      Used Block count 1
      Peak Allocated bytes 2.0 MB
      Failed Allocations. Bucket layout:
        16B: 64 Subsections = 18724 buckets. Failed count: 3889
        32B: 17 Subsections = 3868 buckets. Failed count: 169583
        48B: 31 Subsections = 5771 buckets. Failed count: 39674
        64B: 28 Subsections = 4411 buckets. Failed count: 9981
        80B: 17 Subsections = 2321 buckets. Failed count: 14299
        96B: 6 Subsections = 722 buckets. Failed count: 9384
        112B: 44 Subsections = 4742 buckets. Failed count: 5909
        128B: 49 Subsections = 4778 buckets. Failed count: 8715

在同一项目的发布构建中,分配器内存块大小足够:

[ALLOC_BUCKET]
      Large Block size 4.0 MB
      Used Block count 1
      Peak Allocated bytes 3.3 MB

如果存储桶分配器已满,分配将回退至另一个分配器。使用情况报告显示使用情况统计信息,包括分配失败的次数。如果报告显示的失败次数呈线性增加,则分配失败可能是在计算帧时发生的,而不是在加载时发生的。回退分配对于场景加载来说不是问题,但如果在计算帧时发生,则可能会影响性能。

要避免此类回退分配,请增加内存块大小,并限制新内存块的大小以匹配帧的峰值使用量,而不是匹配场景加载的峰值使用量。这样可以防止内存块变得太大并保留大量在运行时不可用的内存。

提示:性能分析器分配器共享存储桶分配器的实例。可以在性能分析器共享存储桶分配器中自定义此共享实例。

动态堆分配器
线程局部存储 (TLS) 堆栈分配器