R8 如何优化我们的代码(2) -- 空值数据流分析

剪枝

kotlin 复制代码
package org.example

fun <T : Any> coalesce(a: T?, b: T?): T? = a ?: b


fun main() {
    println(coalesce("one", "two"))
    println(coalesce(null, "two"))
}

这段代码比较简单, 对 R8 稍微有点了解的人可能会马上反应过来,这个函数因为过于简单,所以大概率是会被 R8 内联的, 内联以后的代码等效于

go 复制代码
println("one" ?: "two")
println(null ?: "two")

但实际上我们 r8 处理过之后的代码是这样:

你会发现做的比较激进,不只是做了内联,甚至还帮我们做了 Pruning 说人话就是剪枝

这个概念大家自行搜索关键词学习即可,这里就不展开了。我粗浅的理解就是 剪枝的过程就是帮我们排除那些不可能达到的分支代码,并将其移除

空值检查

kotlin 自带空值检查 这个大家肯定都比较熟悉了

kotlin 复制代码
fun String.double(): String = this + this

fun coalesce(a: String?, b: String?): String? = a ?: b

fun main(args: Array<String>) {
    println(coalesce(null, "two")?.double())
}

未使用 r8时,有多条 kotlin 的空值检查语句

使用 r8 之后

多余的空值检查被去除

java中的空值检查

虽然 java 不像 kotlin 中自带空值检查,但是r8 一样对其有着优化

可以看下这个 first 函数

java 复制代码
final class Nulls {
    public static void main(String[] args) {
        System.out.println(first(args));
        if (args == null) {
            System.out.println("null!");
        }
    }

    public static String first(String[] values) {
        if (values == null) throw new NullPointerException("values == null");
        return values[0];
    }
}

需要额外改一下 rules

arduino 复制代码
-keep class Nulls {
   public static java.lang.String first(java.lang.String[]);
}

可以看下未使用 r8 时的指令

使用 r8 之后的指令

显然使用r8 指令之后的 first 方法显的更为高效,因为 null 的条件语句被后置了 从字节码指令的角度来看 显然是 r8 的指令更为效率了

相关推荐
一笑的小酒馆2 小时前
Android中的tcp通信
android
默阳12345 小时前
2026年Android中高级面试题专栏(Android进阶篇)
android
古法安卓6 小时前
Android-日志系统源码解析
android·java·android studio
恋猫de小郭7 小时前
Android 17 + OkHttp 5.5.0 ,全新 ECH 下你的 HTTPS 域名可以请求时被安全隐藏
android·前端·flutter
小强闯江湖7 小时前
不只是让 AI 写代码:ViewCompose 把 Android UI 做成了可编译、可渲染的闭环
android·人工智能·kotlin
hunterandroid8 小时前
StateFlow 与 SharedFlow 的边界:状态与事件的正确建模
android·前端
YF02119 小时前
Android遥控器对频详解
android·android things
码农coding10 小时前
android12 WindowManagerService窗口的布局过程
android·源码
杉氧12 小时前
状态管理变迁史:为什么我们放弃了 Redux 选择 Zustand?
android·前端·react native
三少爷的鞋16 小时前
别再靠 Code Review 守底线:我做了一个静态分析项目 RedLine
android