美文网首页
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