Why Upgrading to AGP 7.0.1 Increased APK Size and How We Fixed It
After upgrading Kuaishou's Android project from AGP 3.4.2 to 7.0.1, the APK size unexpectedly grew despite faster builds, leading to a deep investigation of Dex compression, R8 changes, and build tool versions, ultimately revealing a fastutil library mismatch that was resolved by forcing the correct version.
Background
Kuaishou's main Android app was using a low Android Gradle Plugin (AGP) version 3.4.2, missing out on newer build speed optimizations and features. In February 2022 Google released AGP 7.0.1, so the team upgraded to this version expecting faster builds and smaller packages.
Phenomenon
After the upgrade, the APK size increased by several megabytes and the build time became significantly longer, prompting a two‑week debugging effort.
Problem Investigation
Comparing the APKs before and after the upgrade showed that the Dex files caused the size increase. Although the total Dex size was smaller with AGP 7, its compression ratio dropped.
Compression Tests
<code>./7zz a agp7.7z agp7.dex -m9=Deflate</code><code>./7zz a agp3.7z agp3.dex -m9=Deflate</code>Using different compression algorithms (Deflate, LZMA2) still resulted in larger compressed files for AGP 7, indicating the issue was not with the compression algorithm.
APK Packaging Logic
The packaging task PackageAndroidArtifact invokes IncrementalSplitterRunnable , which creates an ApkFlinger (new zipflinger packager). Switching to the old packager via android.useNewApkCreator did not solve the problem.
<code>@Override
public void doTaskAction(@NonNull InputChanges changes) {
// ...
getTransformationRequest().submit(this, getWorkerExecutor().noIsolation(), IncrementalSplitterRunnable.class, configure(changedResourceFiles, changes));
}</code>Dex Generation Details
R8 version was upgraded from 1.6 to 3.0.73. Tests showed that the smali output of Dex files was identical, but binary inspection revealed differences in the string_ids section.
In AGP 3 the string_data_off offsets are ordered; in AGP 7 they are unordered, reducing compressibility.
<code>private <T> void writeItems(Collection<T> items, Consumer<Integer> offsetSetter, Consumer<T> writer, int alignment) {
if (items.isEmpty()) {
offsetSetter.accept(0);
} else {
offsetSetter.accept(dest.align(alignment));
// iteration became unordered
items.forEach(writer);
}
}</code>The unordered iteration stemmed from Reference2IntLinkedOpenHashMap (fastutil library). The project was pulling fastutil 8.4.0 via com.android.tools.build:builder:7.0.1 , while R8 expected version 7.2.0, causing the bug.
Solution
Force the fastutil version to 7.2.0 in the buildscript classpath:
<code>classpath("it.unimi.dsi:fastutil:7.2.0") {
force true
}</code>After aligning the library versions, the Dex offsets became ordered again, compression improved, and the APK size returned to expected levels.
Conclusion
The size increase was not due to the compression algorithm, R8 code changes, or ProGuard configurations, but to an unordered string_ids offset caused by a mismatched fastutil library version. Aligning the library version resolved the issue and provided insight into AGP packaging, Dex structure, and R8 internals.
References
[1] Dex file format definition: https://source.android.google.cn/docs/core/dalvik/dex-format?hl=zh-cn#file-layout
[2] string_data_off description: https://source.android.google.cn/docs/core/dalvik/dex-format?hl=zh-cn#string-item
Kuaishou Frontend Engineering
Explore the cutting‑edge tech behind Kuaishou's front‑end ecosystem
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.