欢迎光临散文网 会员登陆 & 注册

Huatuo 划时代的Unity原生C#热更新技术

2022-12-22 19:00 作者:unity小能手  | 我要投稿


huatuo介绍

huatuo是一个特性完整、零成本、高性能、低内存的近乎完美的Unity全平台原生c#热更方案。

huatuo扩充了il2cpp的代码,使它由纯AOT runtime变成‘AOT+Interpreter’ 混合runtime,进而原生支持动态加载assembly,使得基于il2cpp backend打包的游戏不仅能在Android平台,也能在IOS、Consoles等限制了JIT的平台上高效地以AOT+interpreter混合模式执行。

基础概念

CLR

CLR即 Common Language Runtime,中文叫公共语言运行时,是让 .NET 程序执行所需的外部服务的集合,.NET 平台的核心和最重要的组件,类似于 Java 的 JVM。更详细介绍请看 公共语言运行时 (CLR) 概述

il2cpp

il2cpp是Unity开发的跨平台CLR解决方案。诞生它的一个关键原因是Unity需要跨平台运行,但一些平台如iOS这种禁止了JIT,导致依赖了JIT的官方CLR虚拟机无法运行,必须使用AOT技术将mananged程序提前转化为目标平台的静态原生程序后再运行。而mono虽然也支持AOT,但性能较差以及跨平台支持不佳。

il2cpp方案包含一套AOT运行时以及一套dll到C++代码及元数据的转换工具,使得原始的c#开发的代码最终能在iOS这样的平台运行起来。

il2cpp与热更新

很不幸,不像mono有Hybrid mode execution,支持动态加载dll,il2cpp是一个纯静态的AOT运行时,不支持运行时加载dll,因此不支持热更新。

目前unity平台的主流热更新方案xlua、ILRuntime之类都是引入一个第三方vm(virtual machine),在vm中解释执行代码,来实现热更新。限于篇幅我们只分析使用c#为开发语言的热更新方案。这些热更新方案的vm与il2cpp是独立的,意味着它们的元数据系统是不相通的,在热更新里新增一个类型是无法被il2cpp所识别的(例如通过System.Activator.CreateInstance是不可能创建出这个热更新类型的实例),这种看起来像、实际上却又不是的伪CLR虚拟机,在与il2cpp这种复杂的CLR运行时交互时,产生极大量的兼容性问题,另外还有严重的性能问题。

一个大胆的想法是,是否有可能对il2cpp运行时进行扩充,添加interpreter模块,进而实现mono hybrid mode execution 这样机制?这样一来就能彻底支持热更新了,并且兼容性极佳。对开发者来说,除了以解释模式运行的部分执行得比较慢,其他方面跟标准的运行时没有区别。

对il2cpp加以了解并且深思熟虑后的答案是——确实是可行的!具体分析参见 关于huatuo可行性的思维实验 。这个想法诞生了huatuo,unity平台第一个支持ios的跨平台原生c#热更新方案!

原理

huatuo扩充了il2cpp运行时,将它由AOT运行时改造为'AOT + interpreter'双引擎的混合运行时,进而完美支持在iOS这种禁止JIT的平台上以解释模式无缝地运行动态加载的dll。如下图所示:

实际使用体验或者特性比较

  • huatuo学习和使用成本几乎为零。huatuo让il2cpp变成全功能的runtime,学习和使用成本几乎为零,几乎零侵入性。而其他方案则有大量的坑和需要规避的规则,学习和使用成本,需要对原项目作大量改造。

  • huatuo可以使用所有c#的特性。而其他方案往往有大量的限制。

  • huatuo中可以直接支持使用和继承主工程中的类型。其他方案要写适配器或者生成代码。

  • huatuo中热更新部分元数据与AOT元数据无缝统一。像反射代码能够正常工作的,AOT部分也可以通过标准Reflection接口创建出热更新对象。其他方案做不到。

  • huatuo对多线程支持良好。像多线程、ThreadStatic、async等等特性都是huatuo直接支持,其他方案除了async特性外均难以支持。

  • huatuo中Unity工作流与原生几乎完全相同。huatuo中热更新MonoBehaviour可以直接挂载在热更新资源上,并且正确工作。其他方案不行。

  • huatuo兼容性极高。各种第三方库只要在il2cpp下能工作,在huatuo下也能正常工作。其他方案往往要大量魔改源码。

  • huatuo内存效率极高。huatuo中热更新类型与主工程的AOT类型完全等价,占用一样多的空间。其他方案的同等类型则是假类型,不仅不能被runtime识别,还多占了数倍空间。

  • huatuo执行效率高。huatuo中热更新部分与主工程AOT部分交互属于il2cpp内部交互,效率极高。而其他方案则是独立虚拟机与il2cpp之间的效率,不仅交互麻烦还效率低下。

运行性能

实际性能如理论估计,全面并且大幅胜出当前主流的xlua、puerts、ILRuntime之类的热更新方案。

  • 基础指令(数值计算及条件跳转等指令),由于各个语言之间差距不大,因此胜出不明显

  • 对象模型指令。由于没有跨语言交互的成本,几乎是数倍到数十倍的提升(如果指令自身消耗特别大,则差距不那么明显)

性能测试用例来自ILRuntime提供的标准测试用例,测试项目来自Don't worry的github仓库。

测试结果显示,绝大多数测试用例都有数倍到数十倍的性能差距,差距极其夸张。唯独数值计算跟xlua有少量劣势,这是因为当前huatuo 未对指令作任何优化 ,后续优化版本大多数基础指令都将有100-300%的性能提升。


Huatuo 划时代的Unity原生C#热更新技术的评论 (共 条)

分享到微博请遵守国家法律