一、摘要
本文从飞书 Android 升级 JDK 11 意外引发的 CI 构建性能劣化谈起,结合高版本 JDK 在 Docker 容器和 GC 方面的新特性,深挖 JVM 和 Gradle 的源码实现,抽丝剥茧地介绍了分析过程和修复方法,供其他升级 JDK 的团队参考。
二、背景
最近飞书适配 Android 12 时把 targetSdkVersion 和 compileSdkVersion 改成了 31,改完后遇到了如下的构建问题。
在 StackOverflow 上有不少人遇到同样的问题,简单无侵入的解决方案是把构建用的 JDK 版本从 8 升到 11。
飞书目前用的 AGP 是 4.1.0,考虑到将来升级 AGP 7.0 会强制要求 JDK 11,而且新版 AS 已经做了铺垫,所以就把构建用的 JDK 版本也升到了 11。
三、问题
升级后不少同学反馈子仓发组件(即发布 AAR)很慢,看大盘指标确实上涨了很多。
除了子仓发组件指标明显上升,每周例行分析指标时发现主仓打包指标也明显上升,从 17m上升到了 26m,涨幅约 50%。
四、分析
1.主仓打包和子仓发组件变成了单线程
子仓发组件指标和主仓打包指标,都在 06-17 劣化到了峰值,找了 06-17 主仓打包最慢的 10 次构建进行分析。
初步分析就有一个大发现:10 次构建都是单线程。
而之前正常的构建是并发的
子仓发组件的情况也一样,由并发发布变成了单线程发布。
2.并发变单线程和升级 JDK 有关
查了下并发构建相关的属性,org.gradle.parallel 一直为 true,并没有更改。然后对比机器信息,发现并发构建用的是JDK 8,可用核心数是 96;单线程构建用的是 JDK 11,可用核心数是 1。初步分析,问题应该就在这里,从 JDK 8 升到 JDK 11 后,由并发构建变成了单线程构建,导致耗时明显上升。而且升级 JDK 11 的修改是在 06-13 合入主干的,06-14 构建耗时明显上升,时间上吻合。
3.整体恢复了并发,但指标没下降
为了恢复并发构建,容易联想到另一个相关的属性 org.gradle.workers.max。
由于 PC 和服务器可用核心数有差异,为了不写死,就试着在 CI 打包时动态指定了 --max-workers 参数。设置参数后主仓打包恢复了并发构建,子仓发组件也恢复了并发。
但观察了一周大盘指标后,发现构建耗时并没有明显的回落,稳定在 25 m,远高于之前 17 m的水平。