#!/usr/bin/env bash # Heap footprint of the same jar on JDK 25, 26 and 27, with compact object headers on and off. # usage: footprint.sh [N products] [runs per configuration] source "$(dirname "$0")/lib.sh" N="${1:-2000000}"; RUNS="${2:-3}" TMP="$(mktemp -d)" MEDS=(); ALL=() row() { # label jdk flags... local label="$1" jh="$2"; shift 2 local idle=() live=() rss=() gcn=() gcms=() ns=() start=() for r in $(seq 1 "$RUNS"); do run_app "$jh" "$N" "$TMP/$label-$r" -Xms1g -Xmx1g "$@" || { echo "$label run $r FAILED"; return; } local d="$TMP/$label-$r" idle+=("$(kv "$d/memory-idle.txt" heapLiveAfterGcMB)") live+=("$(kv "$d/memory.txt" heapLiveAfterGcMB)") rss+=("$(kv "$d/memory.txt" rssMB)") gcn+=("$(kv "$d/load.txt" gcCountDuringLoad)") gcms+=("$(kv "$d/load.txt" gcMillisDuringLoad)") ns+=("$(kv "$d/lookups.txt" nsPerLookup)") ALL+=("${gcn[-1]} ${rss[-1]} ${ns[-1]}") printf 'run %s/%s idle=%sMB live=%sMB rss=%sMB gcDuringLoad=%s (%sms) lookup=%sns compact=%s\n' "$label" "$r" \ "${idle[-1]}" "${live[-1]}" "${rss[-1]}" "${gcn[-1]}" "${gcms[-1]}" "${ns[-1]}" "$(kv "$d/memory.txt" UseCompactObjectHeaders)" done MEDS+=("$(printf 'MED %-22s idle=%sMB live=%sMB rss=%sMB gcDuringLoad=%s gcMs=%s lookupNs=%s' "$label" \ "$(printf '%s\n' "${idle[@]}" | median)" "$(printf '%s\n' "${live[@]}" | median)" "$(printf '%s\n' "${rss[@]}" | median)" \ "$(printf '%s\n' "${gcn[@]}" | median)" "$(printf '%s\n' "${gcms[@]}" | median)" "$(printf '%s\n' "${ns[@]}" | median)")") echo "${MEDS[-1]}" } echo "# $(date -u +%F) ${N} products, -Xms1g -Xmx1g, G1, ${RUNS} runs per configuration; MED lines are medians" echo "# JDK25=$("$JDK25/bin/java" -version 2>&1 | sed -n 2p)" echo "# JDK26=$("$JDK26/bin/java" -version 2>&1 | sed -n 2p)" echo "# JDK27=$("$JDK27/bin/java" -version 2>&1 | sed -n 2p)" row jdk25-default "$JDK25" row jdk25-compact "$JDK25" -XX:+UseCompactObjectHeaders row jdk26-default "$JDK26" row jdk26-compact "$JDK26" -XX:+UseCompactObjectHeaders row jdk27-default "$JDK27" row jdk27-optout "$JDK27" -XX:-UseCompactObjectHeaders echo echo "== medians of $RUNS runs per configuration (idle = live set of the idle app; live = after loading the catalog)" printf '%s\n' "${MEDS[@]}" echo stats() { sort -n | awk '{a[NR]=$1} END{printf "min %d / median %d / max %d", a[1], a[int((NR+1)/2)], a[NR]}'; } echo "== the same runs, grouped by whether a collection ran while the catalog was loading (all configurations together)" for g in zero some; do if [ $g = zero ]; then sel='$1==0'; label="no collection during load"; else sel='$1>0'; label="a collection during load"; fi n=$(printf '%s\n' "${ALL[@]}" | awk "$sel" | wc -l) printf '%-27s runs=%-3s rss MB: %s lookup ns: %s\n' "$label" "$n" \ "$(printf '%s\n' "${ALL[@]}" | awk "$sel {print \$2}" | stats)" "$(printf '%s\n' "${ALL[@]}" | awk "$sel {print \$3}" | stats)" done # keep one histogram per JVM for the class-level table mkdir -p "$MOD/target/hist" for c in jdk26-default jdk27-default jdk27-optout; do cp "$TMP/$c-1/histogram.txt" "$MOD/target/hist/$c.txt"; done rm -rf "$TMP"