Last active
July 9, 2025 02:41
-
-
Save radityagumay/359ef0a947ef24071a6d419858fb02e4 to your computer and use it in GitHub Desktop.
android app bundle size benchmark script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -euo pipefail | |
function usage() { | |
echo "Usage: $0 --base=<baseline.aab> --head=<head.aab>" | |
exit 1 | |
} | |
# ─── Parse args ───────────────────────────────────────────────────────────────── | |
BASE="" HEAD="" | |
for arg in "$@"; do | |
case $arg in | |
--base=*) BASE=${arg#*=} ;; | |
--head=*) HEAD=${arg#*=} ;; | |
*) echo "Unknown argument: $arg"; usage ;; | |
esac | |
done | |
[[ -z "$BASE" || -z "$HEAD" ]] && usage | |
[[ ! -f "$BASE" ]] && echo "✖ Base AAB not found: $BASE" && exit 1 | |
[[ ! -f "$HEAD" ]] && echo "✖ Head AAB not found: $HEAD" && exit 1 | |
# ─── Detect bundletool ────────────────────────────────────────────────────────── | |
if command -v bundletool &>/dev/null; then | |
BUNDLETOOL_CMD="bundletool" | |
elif [[ -f "${BUNDLETOOL:-bundletool.jar}" ]]; then | |
BUNDLETOOL_CMD="java -jar ${BUNDLETOOL:-bundletool.jar}" | |
else | |
echo "✖ bundletool not found. Install via Homebrew or drop bundletool.jar here." | |
exit 1 | |
fi | |
if [[ $BUNDLETOOL_CMD == java* ]]; then | |
command -v java &>/dev/null || { echo "✖ java not on PATH"; exit 1; } | |
fi | |
# ─── Prep temp dir ────────────────────────────────────────────────────────────── | |
TMP=$(mktemp -d) | |
cleanup(){ rm -rf "$TMP"; } | |
trap cleanup EXIT | |
# ─── Collect sizes ────────────────────────────────────────────────────────────── | |
collect_sizes(){ | |
local label=$1 aab=$2 | |
# 1) per-ABI splits (default + local-testing) | |
local split_apks="$TMP/${label}.apks" | |
$BUNDLETOOL_CMD build-apks \ | |
--bundle="$aab" \ | |
--output="$split_apks" \ | |
--mode=default \ | |
--local-testing | |
unzip -q "$split_apks" -d "$TMP/${label}" | |
for abi in armeabi_v7a arm64_v8a x86_64 x86; do | |
# sum up any split APK containing the ABI name | |
local size | |
size=$(find "$TMP/${label}/splits" -type f -name "*${abi}*.apk" -print0 \ | |
| xargs -0 wc -c \ | |
| awk '{sum += $1} END{print sum+0}') | |
eval "${label}_${abi}=$size" | |
done | |
# 2) universal | |
local uni_apks="$TMP/${label}_uni.apks" | |
$BUNDLETOOL_CMD build-apks \ | |
--bundle="$aab" \ | |
--output="$uni_apks" \ | |
--mode=universal | |
unzip -q "$uni_apks" -d "$TMP/${label}_uni" | |
local uni="$TMP/${label}_uni/universal.apk" | |
local size=$(wc -c <"$uni" | tr -d ' ') | |
eval "${label}_universal=$size" | |
} | |
collect_sizes base "$BASE" | |
collect_sizes head "$HEAD" | |
# ─── Helpers ──────────────────────────────────────────────────────────────────── | |
to_mb3(){ echo "scale=3; $1/1024/1024" | bc; } | |
to_mb2(){ echo "scale=2; $1/1024/1024" | bc; } | |
human_diff(){ | |
local b=$1 sign abs | |
if (( b < 0 )); then sign="–"; abs=$(( -b )); else sign="+"; abs=$b; fi | |
if (( abs >= 1048576 )); then | |
local v=$(echo "scale=2; $abs/1048576" | bc) | |
echo "${sign}${v} MB" | |
elif (( abs >= 1024 )); then | |
local v=$(echo "scale=2; $abs/1024" | bc) | |
echo "${sign}${v} KB" | |
else | |
echo "${sign}${abs} B" | |
fi | |
} | |
# ─── Compute metrics ───────────────────────────────────────────────────────────── | |
base_uni=$(to_mb3 "$base_universal") | |
head_uni=$(to_mb3 "$head_universal") | |
diff_uni=$(human_diff $(( head_universal - base_universal ))) | |
for abi in armeabi_v7a arm64_v8a x86_64 x86; do | |
eval "b=\$base_$abi"; eval "h=\$head_$abi" | |
eval "base_mb_$abi=\$(to_mb2 \$b)" | |
eval "head_mb_$abi=\$(to_mb2 \$h)" | |
eval "diff_mb_$abi=\$(human_diff \$(( h - b )))" | |
done | |
# ─── Print table ──────────────────────────────────────────────────────────────── | |
printf "\n%-8s | %-16s | %-12s | %-12s | %-12s | %-12s\n" "" "Universal Apk Size" "armeabi-v7a" "arm64-v8a" "x86_64" "x86" | |
printf "%-8s | %-16s | %-12s | %-12s | %-12s | %-12s\n" "Target" "${base_uni} MB" "${base_mb_armeabi_v7a} MB" "${base_mb_arm64_v8a} MB" "${base_mb_x86_64} MB" "${base_mb_x86} MB" | |
printf "%-8s | %-16s | %-12s | %-12s | %-12s | %-12s\n" "Current" "${head_uni} MB" "${head_mb_armeabi_v7a} MB" "${head_mb_arm64_v8a} MB" "${head_mb_x86_64} MB" "${head_mb_x86} MB" | |
printf "%-8s | %-16s | %-12s | %-12s | %-12s | %-12s\n" "Diff" "${diff_uni}" "${diff_mb_armeabi_v7a}" "${diff_mb_arm64_v8a}" "${diff_mb_x86_64}" "${diff_mb_x86}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment