Android 启动优化
基本操作
-
将启动页主题背景设置成闪屏页图片
这么做的目的主要是为了消除启动时的黑白屏,给用户一种秒响应的感觉,但是并不会真正减少用户启动时间,仅属于视觉优化。
-
主页面布局优化
1)通过减少冗余或者嵌套布局来降低视图层次结构
2)用 ViewStub 替代在启动过程中不需要显示的 UI 控件
-
Application 和 主 Activity 的 onCreate 中异步初始化某些代码
因为在主线程上进行资源初始化会降低启动速度,所以可以将不必要的资源初始化延迟,达到优化的效果。但是这里要注意懒加载集中化的问题,别用户启动时间快了,但是无法在界面上操作就尴尬了。
systrace 查找耗时代码
具体步骤
1)清空手机后台
2)在命令行执行
python $ANDROID_HOME/platform-tools/systrace/systrace.py gfx view wm am pm ss dalvik app sched -b 90960 -a 你的包名 -o test.log.html
这一步需要你系统环境配置了 ANDROID_HOME 环境变量。
3)运行你的App,正常操作到你想测性能的地方,然后再命令行窗口中按 Enter 键停止收集
4)用 chrome(只支持此浏览器)打开生成的 test.log.html 结果文件
目前需要关心的地方就是我们的应用进程相关的,也就是红框圈起来的地方。
图中的 F 代表绘制帧,黄色/红色表示该帧绘制超时,绿色代表绘制正常,也就是在16.6ms内绘制完一帧。
通过 redex 重排列 class 文件
redex 是 Facebook 开源的一款字节码优化工具,目前只支持 mac 和 linux。用的是里面的 interdex 功能来重排列我们 dex 中的 class 文件,通过文件重排列的目的,就是将启动阶段需要用到的文件在 APK 文件中排布在一起,尽可能的利用 Linux 文件系统的 pagecache 机制,用最少的磁盘 IO 次数,读取尽可能多的启动阶段需要的文件,减少 IO 开销,从而达到提升启动性能的目的。
转换时机
-
Android 的编译过程首先是通过 javac 工具将 .java 文件编译成 .class 文件,接着将所有的 .class 文件合并成 Dalvik 虚拟机的可执行文件 .dex,最后再跟其他资源等文件一起压缩成 APK 文件。
-
Redex 选择基于字节码文件而不是 Java 源码进行优化,是因为字节码相比 Java 源码而言,可以进行更为全局的,类与类之间的优化,而不是单个类文件的局部优化;选择基于 dex 字节码而不是 Java 字节码进行优化,是因为某些优化只能在 dex 文件中进行。
手Q初探
优化内容
-
A.内联(删除多余层级)
eg: func1 -> static func2 -> static func3
func1 -> static func3 -
B.删除无用代码,移除空类
-
C.对于只有一个实现类的接口或父类,直接用实现类代替
-
D.SynthPass
内部类B访问外部类A的private static变量,compile后其实是通过生成额外的acces方法来帮助内部类访问外部类私有成员。这个优化可以去除额外生成的字节码,方法相当于把变量的作用域改成public。
-
E.字符串缩减
包括提供字节码层面的混淆能力,类似Proguard,以及DEX文件中metadata的优化。
-
F.Interdex
使用者提供程序启动时加载类序列作为配置文件,按此顺序调整dex中类的顺序,可以有效提升冷启动速度,提升幅度在30%左右。
使用问题
-
A.IlegalAccessError
redex的bug,在内联优化中,移除中间层的方法时没有考虑作用域,比如:
Func1 -> public static func2 -> private static func3
会被优化成:Func1 -> private static func3
而调用类又不能访问其他类的私有方法,导致抛异常(这个问题有不少issue,近期redex似乎已经修复了,还未验证)。 -
B.NoClassDefError
一个比较诡异的问题,运行时报这个错,但反编译Dex文件,这个类是存在的,怀疑是redex的bug,github也有少部分类似的issue,原因未明。
-
C.NoSuchMethodError
一个坑。因为手Q里很多业务是以插件机制运行的,部分插件是非独立的,也就是和手Q工程一起编译,并且会引用手Q代码,在编译完成后,这些插件也分别打包好存放在手q的apk里。这样会导致的问题是:
redex在做优化时可能会把手Q部分方法移除,如果插件刚好引用了这个方法,就出现NoSuchMethodError了。 -
D.Interdex
这个优化项会完全打乱原有的dex分布,甚至dex的数量也会发生改变,用来校验分dex是否注入成功的Foo类,以及补丁patch也被打乱,对启动时分dex注入,补丁等逻辑都有很大影响。
-
E.签名
redex执行后需要对apk重新签名。
遇到问题时,可以把可疑的优化项屏蔽掉,继续验证。可即使如此,屏蔽到最后悲催的发现可用优化项已经不多,优化的效果也不太明显(安装包可以减少100k左右,启动速度方面因为interdex需要较大改动,未尝试)。仅存的几个优化项没经过更细致的测试也可能存在隐患,而就算只使用这少数优化,在编译脚本修改和rdm构建环境搭建上也会有很大的工作量。
支付宝 App 构建优化解析:通过安装包重排布优化 Android 端启动性能
网友评论