redex优化实践一则

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

网络上的资料:

Redex安卓Apk优化技术研究

支付宝 App 构建优化解析:通过安装包重排布优化 Android 端启动性能

Android字节码优化工具redex初探

二、一个成功的例子

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

redex优化实践一则

上一篇:Vue组件引用


下一篇:网卡中断