Version: 1.5
语言 : 中文
Wasm Analysis 工具
引擎代码剔除

托管代码精简

团结引擎小游戏平台新增了 Extreme 级别的托管代码剪裁策略,基于对MonoBehaviourScriptableObject类深入静态分析,尽可能多的剔除代码。

托管代码精简可以缩减构建后的托管程序集的大小,进而减少wasm包的大小,因此对于 il2cpp backend 优化效果较明显。 对于 .net 8 backend 则作用不大,因为托管程序集本身体积就不大,缩减的收益不大。

Managed Code 剔除会对代码进行静态分析。首先依据 root marking rules 标记root类型、方法、属性等,然后再依据 dependency marking rules 去标记这些root的依赖。接下来未被标记的代码会被剔除。新增的 Extreme Level,使用了更加激进的标记规则,与 High Level 对比如下:

Root marking rules 对比

  • High 级别及以下:保留用户代码中所有的 MonoBehaviour 和 ScriptableObject 类。
  • Extreme 级别:只保留被实际用到(通过 Scene 或者 AssetBundle 引用)的 MonoBehaviour 和 ScriptableObject 类。

Dependency marking rules 对比

在依赖标注上:

  • High 级别及以下:保留 MonoBehaviour 和 ScriptableObject 类的所有成员
  • Extreme 级别:仅保留 Unity Event Functions 和实际被使用到的方法

实测剔除效果对比

在4个不同规模的项目上实测的剔除效果对比如下:

与 High Level 一样,基于静态分析的 Extreme 模式也存在误剔除的风险。为此我们新增了 Dryrun 模式,可帮助开发者快速定位与收集误剔除的方法。

Dryrun模式

  • 启用 “Log Stripped Method for Debug” 模式。
  • 在此模式下,托管代码不会真的被剔除。待剔除的方法将被插入警告打印代码。
  • 当这些待剔除的方法被调用时,控制台中会打印出警告信息,这可以帮助开发者快速定位与收集误剔除的方法。

例如微信 SDK 组件挂载问题:某些类型如 WXProfileStatsScript 通过 AddComponent(Type) 挂载,由于类型变量在其他地方赋值,编译时无法确定,导致该类型无法保留。Dryrun 模式下,将打印相应的警告:

补充信息:AddComponent<Type >() 和 AddComponent(typeof(XXX)) 模式的调用则可以通过代码上下文来识别,因此可以被保留。

另一个案例 LitJson 库反射问题:LitJson 库通过反射查找类型的 public 属性。在进行 Managed Code 剔除时,由于通过静态分析无法得知类型的哪些 public 属性将被反射调用,可能导致这些属性的 get/set 方法被误剔除。

注意:只有 il2cpp backend 才支持此模式。.net 8 backend 下此模式不显示。

Wasm Analysis 工具
引擎代码剔除