zifa2003293 发表于 2022-5-16 08:44

Unity C#热更新系列(5)-Wrap和Adapter

本篇将简单讲述一下Wrap与Adapter在C#的作用,它们也将会随着技术的革新,消失在历史的长河中。
一、写在前面

随着跨时代的C#热更新huatuo开源,让我们看到了C#热更新更多的可能,一些我们在纯C#的环境下无法完成的东西,在C++环境下都能比较容易的解决,如:可以直接在GC空间分配我们解释栈空间,让我们的栈空间直接具备对象引用能力。传送门:
二、Adapter开始与消亡

为什么需要适配器?在纯C#环境下,我们对系统类型进行扩展的时候,运行时环境是无法认识我们的热更新类型的, 所以我们需要为我们的热更类型生成一个Adapter,标识我们的热更类型需要工作在某个系统类型下,并且我们还需要开辟一个新的类型系统来管理所有的热更类型,用来作对象类型判定。此时我们的适配将会是



简单对象的适配

我们可以看出为了让系统装下我们的热更数据,我们需要耗费更多的内存来支撑,而且系统还是不认识热更的类型。
但是从内存角度来看,根本就没有类型的说法,对内存来说都是数据,你告诉要多大,它就给你多大,怎么用是应用程序自己说了算。而描述一个类型的内存大小信息,就是元数据信息,这部分内容对IL2CPP来说就是global-metadata.dat中的内容,意味着我们可以修改IL2CPP代码来注入更多的元数据信息,让它认识我们的热更新类型。从而我们就不再需要适配器了,我们的热更新类型与系统类型将不再有任何区别,也不会有额外的内存开销。
三、Wrap

解决了类型问题后,我们还需要解决解释器对任意系统方法进行访问。我们很容易就能得到一个通配方案:反射调用。但是反射导致的GC、装箱拆箱、性能低下问题,我们是无法接受的,因此我们有了第一次的系统API Wrap操作:
1.0版本 通过代码生成的方式,为每个API生成直接调用的方法。这个版本解决了所有的GC问题,但是我们的可执行文件的大小一下就上去了。我们需要考虑新的方案降低可执行文件大小,到此有了2.0版本。
2.0版本 通过挂载委托的方式,相同签名的方法,可以用相同的委托来适配
API:Delegate.CreateDelegate(Type delegateType, MethodInfo method)
(非常推荐在C#中,如果需要反射调用API并且是非一次性调用的,可以通过挂载委托来优化调用,无额外GC且高性能)新版本的改动在调用时也无额外GC,而且性能也不会打折扣,我们的代码量也降了一部分下来,我们是需要适配所有的签名就行了,毕竟C#需要强类型校验,但适配所有方法签名从数量上来说还是有很多。
在C#端我们也就只能做到这一点了,但是从C++角度来看,我们还能进一步调整。根据__cdecl(C语言默认的函数调用)规则(仅x86下):



C语言函数调用栈

参数的传递是按照指定内存规则压栈的,这意味着我们只需要将参数总内存大小的数据传递过去就行了,无需真正的按照真实的参数传递,我们也无需关注参数的类型了,就可以完成一个参数欺骗。此时我们的Wrap将只需要适配所有的返回值大小与参数大小的匹配了。我们的API-Wrap将只需要100来个函数就能搞定了,这下就大大的减小了我们的可执行文件大小了。



按照内存适配的函数调用,完成参数传递与结果传递

四、写在最后

本章内容结合了开源项目huatuo的实现原理为大家讲解,它的到来让我们的热更新回归了本质,从根本上解决热更新的问题,它基本解决了现有热更性的所有诟病,内存上,性能上都非常完美,你只需要按照正常的方式去书写你的代码就行了,无需考虑适配这些问题,因为没有这些问题了,笔者强烈推荐。结尾传送门:
本系列到此提前完结了,已基本讲解完C#热更新实现原理,技术革新了,没有下一篇了。

pc8888888 发表于 2022-5-16 08:46

博主,您好,请问您是因为看到了huatuo的方案,而直接完结这一系列文章了吗?其实您的文章以及思路也很有教学意义,我有一些问题就是看你的文章才明白的。

super1 发表于 2022-5-16 08:56

感谢您的支持,该系列原本打算是还有一篇的,讲述Debugger的实现,对热更新来说算非必须内容,前面的内容已经足够实现热更新了。而且新的方案来说是它的作用变得十分的微弱了,我们打包后用日志观察的情况更多,加上业余时间不多,背后也没有强大的团队,所以就没打算写了。其原理是做中间人攻击,劫持Unity Debugger的流量,过滤出热更脚本断点,然后自己实现热更脚本调试处理,其他脚本调试消息直接放行即可,可以做到同时调试热更与非热更,这样我们只需要做一个中间商就行了,无需再去适配各种IDE,那是Unity的事儿,我们也不用因为热更新去更换我们习惯的IDE(这才是真正的目的,个人觉得不改变原有习惯还能享受其带来的便利的才能算是个好方案吧)。
页: [1]
查看完整版本: Unity C#热更新系列(5)-Wrap和Adapter