其他
IL2CPP优化(中):让虚方法调用更快
虚方法调用是必须在运行时决定的调用。编译器在编译代码时并不知道哪个方法即将被调用,所以它为每个类都构建了方法数组(称为虚函数表,或称vtable)。当有人调用这些方法其中之一的时候,运行时会查找出vtable中正确的方法并且调用它。但是,当这些方法不管用,或者是vtable中没有相应的虚方法以供调用的时候呢?
这个有点古怪的代码在Just-in-time (JIT,即时编译)编译器里运行的时候没有任何问题,它会在运行时进行编译。如果在Unity编辑器中运行,输出结果如下:
但如果使用Ahead-of-time (AOT,预先编译)编译器结果就完全不同了,如果我们在iOS上用IL2CPP运行同样的代码,将出现如下报错信息:
在运行时创建类型(GenericDerivedType<int>)正是导致SayHello虚方法调用产生问题的原因。既然IL2CPP是一个AOT编译器,而且并没有GenericDerivedType<int>类型的源代码,IL2CPP就将无法生成SayHello方法的实现。
下面试试“通常”写调用的方法!如果不是由AOT编译器生成的方法,则用抛出托管异常的方法来替换它。在Unity5.5(目前处于封闭测试阶段的alpha版本)中,GetVirtualInvokeData代码如下:
实际上这是一个常见的虚拟机优化技术,所以我们很高兴能将它应用于IL2CPP。它沿用了古老的关于性能的口头禅:“不执行代码比执行某些代码更好。” 下一篇我们将讨论另一种小优化,如果我们可以证明其中有些代码并不重要,IL2CPP就可以完全避免执行这些代码。
关于本教程如有任何疑问,请点击[阅读原文]进入Unity官方中文论坛提问!
更多Unity技术内容,尽在Unity官方中文社区(forum.china.unity3d.com),请保持关注!