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

huatuo官方技术教程:huatuo之AOT泛型限制及原理介绍

2022-11-29 17:18 作者:游戏开发RAIN  | 我要投稿

中AOT泛型的底层机制及解决方法。知乎的文档格式化有问题,更舒服的版本请看 AOT泛型原理介绍 。

CLR 泛型



CLR中有两类泛型特性:泛型类型和泛型函数。泛型是c#中使用极其广泛的特性。即使一个没有明显包含泛型的用法,可能隐含了泛型相关的定义或者操作。

例如

  • int[]隐含就实现 IEnemrable之类的接口。

  • 为async生成状态机代码时,也会隐含生成一些对 System.Runtime.CompilerServices.AsyncTaskMethodBuilder::AwaitUnsafeOnCompleted 之类的泛型代码的调用。

AOT泛型的问题

泛型类型本身只是元数据,内存可以动态创造出任意泛型类型的实例化,无论是AOT泛型还是解释器泛型。但泛型函数(包括泛型类的普通成员函数)则情况有点不同。

解释器泛型函数没有任何限制,但AOT泛型函数则遇到一个严重的问题:由于泛型函数的原始函数体元数据在il2cpp翻译后已经丢失,理论不可能根据已有的c++泛型函数指针为一个新的泛型类型产生对应泛型实例化函数。

对于一些特殊的AOT泛型,huatuo作了特殊处理,没有限制:

  • 泛型数组,包括多维数组

  • 泛型delegate

  • 泛型Nullable类型

但显然不可能对每个AOT泛型类特殊处理。因此,如果你在热更新脚本里定义了个值类型:

  • class引用类型

reduce type为 object

  • 泛型类型

GenericType<T1,T2,...> 如果是class类型则reduce type为object,否则reduce type为 GenericType<ReduceType<T1>, ReduceType<T2>, ...>。

例如

  • Dictionary<int, string>的reduce type为object。

  • YourValueType<int, string>的reduce type为YourValueType<int,object>

基于补充元数据的泛型函数实例化技术(huatuo的专利技术)

既然AOT泛型函数无法实例化的问题本质上是il2cpp翻译造成的元数据缺失的问题,那解决思路也很简单,补充上原始元数据那就能正常实例化了。使用 HuatuoApi.LoadMetadataForAOTAssembly 函数为AOT的assembly补充对应的元数据。

注意,当前要求补充的dll与打包时裁剪后的dll精确一致,因此必须使用build过程中生成的裁剪后的dll,则不能直接复制原始dll,这个限制将来可能会去掉。这些dll可以在目录 {project}/Temp/StagingArea/Il2Cpp/Managed 下找到。另外,对于一些平台如Win Standalone的包,在 {build}/{project}/Managed 目录下也能找到。

你只要在使用AOT泛型前调用即可(只需要调用一次)。如果未注册相应的泛型元数据,则退回到il2cpp的泛型共享机制。

基于补充元数据的泛型函数实例化技术虽然相当完美,但毕竟实例化的函数以解释方式执行,如果能提前在AOT中泛型实例化,可以大幅提升性能。 所以推荐对于常用尤其是性能敏感的泛型类和函数,提前在AOT中实例化。后续我们也会提供工具帮助自动扫描收集相应的泛型实例。

以下代码来自 huatuo_trial 。


huatuo官方技术教程:huatuo之AOT泛型限制及原理介绍的评论 (共 条)

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