Facebook APP优化工具ReDex

https://github.com/facebook/redex

Redex是专门的用于Android字节码的优化,在apk大小、运行速度上都有优化。

Redex基于管道的方式来优化Android的 .dex文件,一个源.dex文件通过管道进行一系列的自定义转换后,将得到一个优化的.dex文件。

Redex优化的时机

Redex选择基于字节码文件而不是java源码进行的优化,即在.dex后进行优化。

这样的优化更为全面,且某些优化只能在dex中进行。

管道的概念

Redex的优化是链式的,方便的对优化进行裁剪。

Redex默认的管道功能支持(在config/default.config):

{
  "redex" : {
    "passes" : [
      "ReBindRefsPass",
      "BridgePass",
      "SynthPass",
      "FinalInlinePass",
      "DelSuperPass",
      "SingleImplPass",
      "SimpleInlinePass",
      "StaticReloPass",
      "RemoveEmptyClassesPass",
      "ShortenSrcStringsPass"
    ]
  }
}

Redex做了哪些优化

进一步混淆和压缩

对字节码做类似于java层的proguard混淆操作。

使用内联函数

内联函数是在编译期间将函数体直接嵌入该函数的调用处,也就是在编译时不具备函数的性质,不存在执行函数调用产生的开销,从而得到提高代码运行性能的目的,同时,如果正确的应用它,还可以减小编译后生成的文件大小。

最简单的一个例子是适配器类型的函数,这些函数通常是用来封装一些小函数,以提供更简洁统一的 API 接口,或者是由于参数列表不同而存在的多个重载函数,亦或者是setter/getter 函数等,这些函数在最终生成的 APK 中有的可能根本不会被调用到。因此在 .dex 文件阶段对这些函数进行内联操作,是很大的一个优化点。

无用代码的消除

无用代码的移除类似于标记清除(mark-sweep)垃圾回收算法。我们从某个明确会调用的入口,例如 MainActivity 开始遍历各个条件分支和函数调用,在生成的图中标记访问到的代码,在遍历了所有的条件分支和函数调用之后,就可以判定那些没有被标记的函数是无用的代码,可以安全的删除。

对于只有一个实现类的接口或父类,直接用实现类代替

基于反馈(启动加载顺序测试)的 Class 字节码布局

类字节码在单个 Dex 中的布局是根据编译顺序而不是运行时行为决定,即便 Multidex 会将 App 定义的组件以及部分启动需要的类放在 Main Dex 中,但依然不是根据运行时顺序布局,这会导致程序启动时需要查找随机分布在 Dex 中的类。

ReDex 会将 APK 在 Lab 中试运行,并跟踪启动时哪些类需要加载,然后将这些类字节码放到 Dex 前部,减少启动时从闪存中寻找类的时间,从而提高 App 启动速度。

results matching ""

    No results matching ""