美文网首页
Android 启动优化

Android 启动优化

作者: 卡路fly | 来源:发表于2020-04-03 15:11 被阅读0次

Android 启动优化

基本操作

  1. 将启动页主题背景设置成闪屏页图片

    这么做的目的主要是为了消除启动时的黑白屏,给用户一种秒响应的感觉,但是并不会真正减少用户启动时间,仅属于视觉优化。

  1. 主页面布局优化

    1)通过减少冗余或者嵌套布局来降低视图层次结构
    2)用 ViewStub 替代在启动过程中不需要显示的 UI 控件

  1. 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 端启动性能

启动优化

启动优化


相关文章

网友评论

      本文标题:Android 启动优化

      本文链接:https://www.haomeiwen.com/subject/ydghphtx.html