版本:Unity 6 (6000.0)
语言:英语
垃圾回收器概述
禁用垃圾回收

增量式垃圾回收

增量式 垃圾回收 (GC) 将垃圾回收过程分散到多个帧中。这是 Unity 中默认的垃圾回收行为。

To enable incremental garbage collection, open the Player Settings and enable Use incremental GC. This is enabled by default.
要启用增量式垃圾回收,请打开“Player Settings”并启用“Use incremental GC”。默认情况下启用此选项。

Unity 的垃圾回收器使用 Boehm–Demers–Weiser 垃圾回收器。默认情况下,Unity 在增量模式下使用它,这意味着垃圾回收器将其工作量分散到多个帧中,而不是停止主 CPU 线程 (停止世界垃圾回收) 来处理托管堆上的所有对象。这意味着 Unity 对应用程序的执行进行了较短的中断,而不是长时间中断以让垃圾回收器处理托管堆上的对象。

增量模式不会使垃圾回收总体上更快,但由于它将工作量分散到多个帧中,因此减少了与 GC 相关的性能峰值。这些中断被称为 **GC 峰值**,因为它们在 性能分析器窗口 的帧时间图中显示为较大的峰值。

如果禁用增量模式(**菜单:Edit > Project Settings > Player > Other Settings > Configuration > Use Incremental GC**),则垃圾回收器在执行收集过程时必须检查整个堆。这被称为 **停止世界** 垃圾回收,因为每当垃圾回收器运行时,它都会停止主 CPU 线程。它只会在处理完托管堆上的所有对象后恢复执行,这可能会导致 GC 峰值影响应用程序的性能。垃圾回收器也是非压缩的,这意味着 Unity 不会在内存中重新分配任何对象以关闭对象之间的间隙。

**重要提示:**Web 平台不支持增量式垃圾回收。

当禁用增量式垃圾回收时,当 Unity 停止运行您的程序代码以执行垃圾回收时,会发生 GC 峰值。此延迟可能持续数百毫秒,具体取决于垃圾回收器需要处理的分配数量以及应用程序运行的平台。

这对实时应用程序(如游戏)来说是个问题,因为当垃圾回收器挂起应用程序的执行时,您的应用程序很难保持流畅动画所需的持续帧速率。

增量式垃圾回收示例

性能分析器中的以下屏幕截图说明了增量式垃圾回收如何减少帧速率问题

Profiling session with Incremental GC enabled
启用增量式 GC 的性能分析会话
Profiling session with Incremental GC disabled
禁用增量式 GC 的性能分析会话

在上面的性能分析会话中,**增量式 GC** 已启用。应用程序具有稳定的 60fps 帧速率,因为垃圾回收器将垃圾回收操作分散到多个帧中,并使用每个帧的一小段时间片 (黄色 VSync 轨迹正上方的深绿色边缘)。

下面的性能分析会话已禁用 **增量式 GC**,并且可以看到一个清晰的 GC 峰值。此峰值会中断原本平滑的 60fps 帧速率,并将垃圾回收发生的帧推迟到超过保持 60fps 所需的 16 毫秒限制。

如果您的应用程序使用 VSync垂直同步 (VSync) 是一种显示设置,它将游戏的帧速率限制为与显示器的刷新率匹配,以防止图像撕裂。
参见 术语表
Application.targetFrameRate,Unity 会根据剩余的可用帧时间调整分配给垃圾回收的时间。这样,Unity 可以在原本花费在等待的时间内运行垃圾回收,并以最小的性能影响执行垃圾回收。

**注意:**如果将 **VSync Count** 设置为除 **Don’t Sync** 之外的任何值(在项目的 质量设置 中或使用 Application.VSync 属性),或者启用 Application.targetFrameRate 属性,Unity 会自动使用给定帧结束时剩余的任何空闲时间进行增量式垃圾回收。

要更精确地控制增量式垃圾回收行为,可以使用 Scripting.GarbageCollector 类。例如,如果您不想使用 VSync 或目标帧速率,可以自己计算帧结束前可用的时间,并将该时间提供给垃圾回收器使用。

禁用增量式垃圾回收

增量式垃圾回收可能会对您的应用程序造成问题,因为当垃圾回收器在此模式下划分工作时,它也会划分标记阶段。标记阶段是垃圾回收器扫描所有托管对象以确定哪些对象仍在使用以及可以清理哪些对象的阶段。

当对象之间的大多数引用在工作片段之间没有改变时,划分标记阶段效果很好。但是,当对象引用发生变化时,垃圾回收器必须在下次迭代中再次扫描这些对象。这意味着太多的变化可能会压倒增量式垃圾回收器,并创建一个情况,即标记阶段永远不会完成,因为它总是有更多工作要做。如果发生这种情况,垃圾回收器将回退到执行完全的非增量式收集。

当 Unity 使用增量式垃圾回收时,它会生成额外的代码(称为写入屏障)以在引用发生更改时通知垃圾回收器,以便它知道是否需要重新扫描对象。这会在 更改引用 时增加一些开销,这对托管代码的性能有影响。

要禁用增量式垃圾回收,请打开“Player Settings”窗口(**Edit > Project Settings > Player > Configuration**)并禁用 **Use Incremental GC**。大多数 Unity 项目都受益于增量式垃圾回收,尤其是如果它们受到垃圾回收峰值的影响,但您始终应该使用 性能分析器帮助您优化游戏的窗口。它显示在游戏的各个区域中花费了多少时间。例如,它可以报告渲染、动画或游戏逻辑中花费的时间百分比。 更多信息
参见 术语表
验证应用程序是否按预期执行。

垃圾回收器概述
禁用垃圾回收