首页 > 其他分享 >Unity热更技术对比(Lua、ILRuntime、HybridCLR)

Unity热更技术对比(Lua、ILRuntime、HybridCLR)

时间:2022-10-12 14:24:27浏览次数:88  
标签:ILRuntime il2cpp HybridCLR IL2CPP Lua AOT 内存 代码

热更技术原理:app+脚本解释器+脚本代码,动态执行最新代码,实现热更。

解释器:

  • Lua技术 = Lua解释器+Lua脚本;
  • C# = C#解释器+c#脚本

Unity的热更方案:

  • Lua解决方案(如ToLua,xLua等):内置Lua虚拟机+UnityEngine与C#框架的接口导出+Lua代码。
  • C#解决方案(ILRuntime):内置.net字节码解释器(虚拟机)+解释执行.net字节码。
  • 内置虚拟机(lua的虚拟机或者IL虚拟机,均基于栈实现):自己解释执行的一个运行环境,在里面解析执行指令(lua虚拟机的指令/IL语句)
  • 这些热更新方案的VM(虚拟机)与IL2CPP是独立的,意味着它们的元数据系统是不想通的,所以无法直接继承MonoBehaviour(IL2CPP级别的数据对象),导致了以下问题:要封装一层;跨域访问;接口导出;不符合标准的Unity开发。

HybridCLR(huatuo)方案:基于IL2CPP

  • 在Unity的il2cpp里面添加一个可以装载.net字节码,解释执行.net的字节码的功能。
  • IL2CPP runtime环境(IL2CPP VM)编写一个解释器,解释执行IL代码指令+使用的是AOT的数据内存对象
  • IL2CPP 数据内存+代码逻辑指令(二进制机器指令)
  • IL2CPP_huatuo 数据内存+代码逻辑指令(二进制机器指令)+ IL代码指令解释执行

HybridCLR技术实现:

  • MetadataCache::LoadAssemblyFromBytes(C#层调用Assembly.Load时触发)时加载并注册interpreter Assembly。
  • IL2CPP运行过程中延迟初始化类型相关元数据,其中的关键为正确设置了MethodInfo元数据中methodPointer指针。
  • IL2CPP运行时通过methodPointer或者methodInvoke指针,再经过桥接函数跳转,最终执行了Interpreter::Execute函数。
  • Execute函数在第一次执行某Interpreter函数时触发HiTransform::Transform操作,将原始IL指令翻译为HybridCLR的寄存器指令。
  • 执行该函数对应的HybridCLR寄存器指令,实现执行最新的代码效果。

huatuo热更可以随意继承使用GameObject,MonoBehvaviour数据对象,而不用像其它热更方案一样去封装类型传递。

在AOT编译时已经把类型编译进去,解释执行时IL运行时的new Obj和AOT里的new Obj是同一个数据对象。

脚本类与AOT类在同一个运行时内,可以随意写继承、反射、多线程(volatile、ThreadStatic、Task、async)之类的代码。不需要额外写任何特殊代码、没有代码生成,也没有什么特殊限制。

HybridCLR优势:

  • 直接使用AOT项目中的内存对象,内存占用、跨域都没问题,性能好、内存占用少;
  • 直接unity+c#开发,不用内置虚拟机,不用弄多一个热更项目;
  • 使用普通的Unity模式开发,不用特殊开发模式。

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

HybridCLR是原生的c#热更新方案。通俗地说,il2cpp相当于mono的aot模块,HybridCLR相当于mono的interpreter模块,两者合一成为完整mono。HybridCLR使得il2cpp变成一个全功能的runtime,原生(即通过System.Reflection.Assembly.Load)支持动态加载dll,从而支持ios平台的热更新。

正因为HybridCLR是原生runtime级别实现,热更新部分的类型与主工程AOT部分类型是完全等价并且无缝统一的。可以随意调用、继承、反射、多线程,不需要生成代码或者写适配器。

其他热更新方案则是独立vm,与il2cpp的关系本质上相当于mono中嵌入lua的关系。因此类型系统不统一,为了让热更新类型能够继承AOT部分类型,需要写适配器,并且解释器中的类型不能为主工程的类型系统所识别。特性不完整、开发麻烦、运行效率低下。

huatuo技术原理:

  • Unity打包运行为:AOT(本地机器指令执行)+IL2CPP VM(提供基础服务支撑,如GC,线程创建等)。
  • Unity项目运行:数据内存对象+AOT代码机器指令
  • HybridCLR项目运行:数据内存对象+AOT代码机器指令+Interpreter IL指令解释执行

方案对比:

一、可热更范围对比

1、Lua方案:
  • 使用Lua开发的脚本都可以热更,C#的脚本不能热更。更改C#的脚本要重新导出类型后重新出包。
2、ILRuntime方案:
  • 由Unity内置.net字节码解释器,分两个项目,热更项目里的c#代码可以热更,主框架里的c#代码无法热更。
3、HybridCLR:
  • 在IL2CPP VM中内置一个.net字节码解释器,会把.net里的数据对象映射到native的数据对象,所以全部的c#代码都可以热更。如果需要热更就装载到IL2CPP VM解释执行,不需要热更就使用原来的AOT的代码。理论上可以更新任何代码

二、新旧版本性能对比

1、HybridCLR:
  • 新版本重新出包时,可以把需要之前热更的dll直接加入到AOT模式去执行;新版本native性能会比解释执行性能要好。
2、其它方案:
  • 每个版本都是解释执行,效率不会有提升

三、解释执行时性能对比

1、HybridCLR:
  • 在解释执行时IL字节码时,先把字节码对象内存映射成native内存块,所以执行IL字节码时能直接访问native内存对象。
2、其它方案:
  • 由于是内置了虚拟机,所以热更代码的内存是运行在虚拟机域的内存对象,在访问native c#对象时,要做一层转化和用函数包起来访问,会增加内存占用(多了对象头和内存对齐)
HybridCLR兼容性:
  • 支持2019.4.x、2020.3.x、2021.3.x系列LTS版本
  • 支持所有il2cpp支持的平台。目前测试支持 PC(Win32和Win64)、macOS(x86、x64、Arm64)、Android(armv7、armv8)、iOS(64bit)、NS(64bit)、WebGL(有少量bug)平台,剩余平台有待测试。
  • 测试过大量游戏常见库,未发现跟il2cpp原生兼容但使用HybridCLR后不兼容性的库。只要能在il2cpp backend下工作的库都可以在HybridCLR下正常工作。甚至那些与il2cpp因为AOT问题不兼容的库,现在因为HybridCLR对il2cpp的能力扩充,反而可以正常运行了。

HybridCLR:https://github.com/focus-creative-games/HybridCLR

https://focus-creative-games.github.io/hybridclr/about/#文档

标签:ILRuntime,il2cpp,HybridCLR,IL2CPP,Lua,AOT,内存,代码
From: https://www.cnblogs.com/wwhhgg/p/16784367.html

相关文章

  • 利用多线程+countDownluanch 优化查询接口提升效率10倍以上
    最近在做工单系统的生产调优,客户想要单子秒出花了一天时间定位问题,发现查询MySQL、Mongo、Redis查询耗时都很小,在0~4ms耗时较大的是一段给activity中form的field设......
  • Lua5.3源码解析
    2022-10-11,16点52 大概看了2个月不到的时间,坚持每天看lua设计与实现.pdf还有csdn上面lua的博客.然后自己debug研究.最后把细节加到注释里面.建议看这个项目时候......
  • Linux下的lua和boost c++的搭建和安装
    先下载lua,boostc++​​http://www.lua.org/versions.html#5.2​​​​http://www.boost.org/​​ ​​http://sourceforge.net/projects/luabind/​​1.安装lua[root@l......
  • redis使用lua脚本
    Lua是什么:Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行。其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。为什么使用:(1)减少......
  • UnLua支持TFunction
    需求在c++使用TFunction接受Lua传过来的闭包函数,调用后调用Lua函数,并能正确的获得返回。扩展Get//yaotemplate<typenameR,typename...Args>FORCEINLINETFunct......
  • 记录用wrk压测脚本lua的一个疑问
    lua脚本的动态传参,例如ThirdOrderNo有幂等校验,不能重复备注:生成随机数,且不重复 math.randomseed(tostring(os.time()):reverse():sub(1,6))例如email需要动态传参,例如t......
  • nginx ngx_http_addition_module 模块openresty content_by_lua 不能生效的原因
    nginx的ngx_http_addition_module模块也是一个修改content的好东西,对于openresty我们经常使用content_by_lua阶段处理但是经过分析ngx_http_addition_module源码的......
  • redis中lua脚本实战
    redis的lua脚本说明lua脚本其实是一个语言,有完整的程序控制语法和一些简单的特殊的数据结构比如table。不依赖于redis的,但是lua脚本是c写的一个非常简单的语言,所以redis也......
  • Lua - 注意点
    数值计算一a=5b=2--输出结果为2.5,因为Lua中表示数值类型的只有一个numberprint(a/b);数值运算二a="1"b="3"--使用加号时,先将加号两边的数值转换成n......
  • Lua-基本语法
    Lua作为动态语言,变量定义的时候不需要声明类型。Lua数据类型--nil表示一个无效值,在条件判断语句中表示false.--boolean表示false和true.--number数值,无论是浮点......