【C#学习】GC停世界
unity有个很重要的性能优化点是减少堆内存分配以减少GC(垃圾内存回收),为什么?
内容来源GPT,仅记录
堆内存和栈内存见https://blog.csdn.net/m0_73117967/article/details/144795238
1. GC 需要“安全点”
-
在 .NET/Mono/IL2CPP 里,GC(垃圾回收器)要清理堆内存中的对象。
-
它必须知道哪些对象还在被引用(活着),哪些已经没人用了(可以释放)。
-
为了得到一个确定的对象图,GC 会要求所有线程都 暂停在安全点,这样它才能正确扫描引用。
2. 为什么要暂停所有线程?
-
如果不暂停,程序可能在 GC 扫描时修改引用:
-
例:GC 正在检查 A 对象是否还在用,另一线程却刚把 A 放进了一个 List。
-
这样就会出现 “悬空引用” 或 “误释放”,导致崩溃。
-
-
所以最简单、最安全的做法就是 停下整个世界(Stop-The-World),让 GC 独占 CPU,确保引用关系稳定。
3. Unity 的特殊性
-
Unity 用的是 Mono/IL2CPP 的托管堆,GC 是 非并行、非增量 的(虽然 Unity 新版本有增量 GC 选项,但限制多)。
-
这意味着当 GC 运行时,渲染、物理、脚本逻辑都会停下,用户就会看到 帧冻结/卡顿。
4. 在游戏里为什么特别明显?
-
游戏追求稳定帧率,比如 60FPS → 每帧时间预算只有 16.6ms。
-
如果一次 GC 扫描花掉 20ms~50ms,就会直接“跳过”一帧甚至多帧 → 屏幕画面会肉眼可见地卡住。
-
在 VR/AR(90FPS~120FPS)里预算更紧,GC 停顿更致命,可能造成眩晕。