通过Kotlin DEX字节码分析在无JIT编译器情况下的Java安卓应用性能提升

I. 引言

Java一直被用作Android应用开发语言。近年来,许多安卓应用程序也开始使用一种新语言Kotlin进行开发。用Java和Kotlin编写的安卓应用程序的源代码会被编译成Java虚拟机(JVM)字节码,再编译为Dalvik可执行文件(DEX)字节码[1],然后在ART(Android运行时)上执行。ART可以使用JIT(即时编译)和AOT(提前编译)编译器将DEX字节码编译为原生代码。

在本文中,我们评估了在没有JIT编译的情况下用Java和Kotlin语言编写的应用程序的性能,基于DEX字节码讨论了性能差异的原因,并提出了一种通过修改DEX字节码来提高性能的方法。

II. 相关工作

在我们之前的工作[2]中,我们比较了图1中描述的Kotlin和Java中for语句的性能,并表明如图2所示,用Kotlin编写的for语句比用Java编写的快7%。随后,我们分析了从用Java和Kotlin编写的源代码生成的处理for语句的DEX字节码。图3和图4显示了这些字节码。从中我们指出,性能差异是由goto指令目标的不同所导致的。接着,我们提出了一种方法,通过将来自Java的for语句处理性能进行改进,使其goto指令的目标修改得类似于Kotlin的方式。原始DEX字节码中goto状态的目标是一个const指令,该指令无需重复执行,而提出的方法将其更改为目标是转到下一条指令,如图5所示。

此方法使程序相较于Java略有改进。然而,修改后的Java程序性能仍低于Kotlin,因此for语句处理仍有进一步改进的空间。

Banerjee等人比较了用Java和Kotlin语言实现的程序的性能[3]。他们随后指出,在某些情况下,Java的性能更高。然而,他们并未讨论提升性能的方法。在[4][5]的研究中,我们评估了安卓应用程序的性能以及通过修改开源的安卓操作系统来研究应用程序行为的提出的方法。然而,这些讨论并未涉及Kotlin的语言处理器。

示意图0

示意图1

示意图2

示意图3

示意图4

III. 提出的方法

在本节中,我们提出了一种方法,通过比现有方法[2]更高级的DEX字节码修改,提升由Java生成的for语句的性能,使其达到与Kotlin生成的for语句相当的水平。该方法将由Java生成的DEX字节码修改为等效于Kotlin生成的for语句指令。即,提出的方法按如下方式转换字节码。

1) 它生成const指令并将其设置为1,即步长。
2) 它使用add-int指令和上述常量来增加循环计数器。
3) 它更改了goto指令的目标。

图6显示了修改后的字节码。在这项工作中,我们手动对其进行了修改,即手工优化。

IV. 评估

我们在实验终端(Pixel 3a,CPU:高通骁龙670,内存:4GB,操作系统:安卓9.0.0,运行环境:ART,JIT已禁用)上评估了前一节提出的ART方法的性能。结果如图7所示。这表明该性能的提出的方法相比正常方法和现有方法分别提升了7%和2%。Kotlin派生应用与Java派生应用在性能上的差异变得非常小。

V. 讨论

在本节中,我们讨论如何实现我们的方法。在本文中,我们通过手动翻译DEX字节码来评估我们的方法。我们认为,该方法可以很容易地实现,无需修改Java编译器,而是构建一个DEX字节码修改器。首先,所提出的系统将DEX字节码转换为DEX助记符。其次,系统通过查找两个连续的const指令和跳转到第二个const指令的goto指令,来识别for语句对应的DEX助记符。第三,系统根据第三节中提出的方法修改这些助记符。最后,系统将修改后的助记符重新转换为DEX字节码文件。

VI. 结论

在本文中,我们比较了在没有JIT编译器的情况下,Java和Kotlin中for语句在ART上的性能,并表明其性能差异是由它们的DEX字节码引起的。随后,我们提出了一种方法,通过将Java生成的应用程序的DEX字节码修改为与Kotlin生成的DEX字节码相同,从而提升其性能。

我们计划实现提出的方法的转换器,并利用现有应用程序评估该方法,同时结合安卓应用程序生命周期[6]讨论两种语言的性能。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐