redex优化实践一则
一、背景资料
ReDex: An Android Bytecode Optimizer
ReDex is an Android bytecode (dex) optimizer originally developed at Facebook. It provides a framework for reading, writing, and analyzing .dex files, and a set of optimization passes that use this framework to improve the bytecode. An APK optimized by ReDex should be smaller and faster than its source.
引用官方仓库的介绍,这个工具用于优化apk里的dex文件,主要的作用是减小代码体积,提升运行速度。
下面是一些资料链接
官方网站:
https://github.com/facebook/redex
https://fbredex.com/docs/usage
网络上的资料:
支付宝 App 构建优化解析:通过安装包重排布优化 Android 端启动性能
二、一个成功的例子
tv上的一个app,《小乌龟不孤单》
dumpsys package org.tongyan.xiaowuguibugudan
Packages:
Package [org.tongyan.xiaowuguibugudan] (42c2dde8):
versionCode=1 targetSdk=14
versionName=1.0.0
signatures=PackageSignatures{427f0d40 [42881e58]}
优化效果
《小乌龟不孤单》
文件大小优化效果:33.29kb,0.16%
优化前:20408765
优化后:20374673
启动速度优化效果:6.96%
优化前:561.4ms
659+560+541+542+659+486+506+441+498+722
优化后:522.3ms
440+538+538+438+550+499+644+558+479+539
操作步骤
- 下载编译
HAHA@HAHA:~/github/
git clone https://github.com/facebook/redex.git
cd redex-master
autoreconf -ivf && ./configure && make
sudo make install
- 在4.4的tv上安装该app,统计十次优化前的启动速度
am start -W org.tongyan.xiaowuguibugudan/org.tongyan.artbook.testAnd && sleep 2 && am force-stop org.tongyan.xiaowuguibugudan
-
adb pull到本地后,装到模拟器上获取dumpheap。
因为tv设备是user的,app也是第三方的user,所以需要一个debug的设备抓am dumpheap。
操作是冷启动app,然后执行命令。目的是拿到冷启动的类加载顺序数据,用于下一步的dex重排布。
am dumpheap YOUR_PID /data/local/tmp/wugui.hprof
- 把hprof拿下来解析出class
HAHA@HAHA:~/github/redex-master$
adb pull /data/local/tmp/wugui.hprof
python3 ./tools/hprof/dump_classes_from_hprof.py --hprof ./wugui.hprof > list_of_classes.txt
- 修改配置config/default.config添加InterDexPass
25 "LocalDcePass",
+ "InterDexPass",
27 "ReduceGotosPass" # This pass should come at the very end, after all other code transformations that might add gotos
28 ]
29 },
+ "coldstart_classes": "list_of_classes.txt",
添加加号的两行。
- 执行redex.py开始重排并重新签名
HAHA@HAHA:~/github/redex-master$
./redex.py -c config/default.config org.tongyan.xiaowuguibugudan-1.apk -o wugui.apk
HAHA@HAHA:~/.android$ apksigner sign --ks debug.keystore wugui.apk
Keystore password for signer #1: android
- 卸载优化前apk,安装优化后apk测试十次启动速度
三、失败的记录
Bad dex magic dex 039 and support_dex_version is 35
https://github.com/facebook/redex/issues/633
redex不支持039的dex。android11编出来的默认是39。
~/redex-master/libredex/DexLoader.cpp
28 static void validate_dex_header(const dex_header* dh,
29 size_t dexsize,
30 int support_dex_version) {
31 bool supported = false;
32 switch (support_dex_version) {
33 case 38:
34 supported = supported ||
35 !memcmp(dh->magic, DEX_HEADER_DEXMAGIC_V38, sizeof(dh->magic));
36 FALLTHROUGH_INTENDED; /* intentional fallthrough to also check for v37 */
37 case 37:
38 supported = supported ||
39 !memcmp(dh->magic, DEX_HEADER_DEXMAGIC_V37, sizeof(dh->magic));
40 FALLTHROUGH_INTENDED; /* intentional fallthrough to also check for v35 */
41 case 35:
42 supported = supported ||
43 !memcmp(dh->magic, DEX_HEADER_DEXMAGIC_V35, sizeof(dh->magic));
44 break;
45 default:
46 not_reached_log("Unrecognized support_dex_version %d\n",
47 support_dex_version);
48 }
49 always_assert_log(supported, "Bad dex magic %s for support_dex_version %d\n",
50 dh->magic, support_dex_version);
但是后来AS上捣鼓修改了gradle弄出了35也没找到具体影响因素。这个magic code,应该是和android编译用的sdk版本有关。
example app没有效果
example app就是用AndroidStudio新建的空的例子app。
没有效果是说启动速度看不出效果,无论是11上还是4.4上。因为空的app没有自己的代码填充在启动流程里,没有耗时因素。
在art虚拟机上启动速度效果不明显
Android字节码优化工具redex初探这篇博客已经测试过了,我这里也一样。也就是android5之前的设备效果才好。
体积优化效果明显的例子
https://github.com/AndroidAdvanceWithGeektime/Chapter22
这个例子里引入了许多的第三方开源库,体积优化效果明显,但是启动优化的还是没有体现
multidex的apk异常
一开始的想法,用体积大的多个classes.dex的apk来做测试,效果会明显些吧,但事与愿违。
redex后,启动要么启动时狗带,要么生命周期正常但是没显示窗口黑屏。伴随着一些找不到方法的dalvikvm和System.err异常日志
W/dalvikvm(14746): VFY: unable to resolve static method
I/dalvikvm(14746): VFY: unable to resolve interface method
I/dalvikvm(14746): Could not find method
W/dalvikvm(14746): VFY: unable to resolve virtual method
W/System.err(14746): java.lang.NoSuchMethodError:
四、总结
目前我这里的测试实践来看,dalvik虚拟机上,只有一个classes.dex的apk《小乌龟不孤单》是顺利得出了优化结果,冷启动速度优化明显,6.96%。体积优化不明显33.29kb,0.16%。
redex有用吗?有用。不过需要有一些约束条件,并且实践落地上可能会需要更进一步的做处理应对。
最严重的问题应该是multidex,应该需要结合自己的项目手动重排,像支付宝这样:支付宝 App 构建优化解析:通过安装包重排布优化 Android 端启动性能