#!/usr/bin/env bash # The smallest container that can hold the catalog, before and after. For each memory limit the app is started # inside a cgroup with that limit and asked to load N products; the table says what happened. # ok the load finished # java-OOM the JVM threw OutOfMemoryError: the heap (a fraction of the limit) was too small # killed(...) the kernel killed the process: total memory, not just heap, went over the limit # no-result-in-25s the JVM stayed alive but the load (about a second when healthy) did not finish in 25 # seconds: the heap is so tight that the collector runs continuously and makes no progress # Each cell is RUNS runs ("3/3 ok" = all three finished); a cell near the boundary can be mixed. # usage: container-sizing.sh [N products] [runs per cell] source "$(dirname "$0")/lib.sh" N="${1:-2000000}"; RUNS="${2:-3}" TMP="$(mktemp -d)"; RETRIES=0 MB=$((1024*1024)) sweep() { # title, jvm-flags-for-all, limits... local title="$1" common="$2"; shift 2 echo "== $title" printf '%-8s %-8s %-30s %-30s %-30s\n' "limit" "heap" "JDK 26 default" "JDK 27 default" "JDK 27 opt-out" for lim in "$@"; do local cells=() heap="?" for cfg in "26|$JDK26|" "27|$JDK27|" "27o|$JDK27|-XX:-UseCompactObjectHeaders"; do IFS='|' read -r tag jh fl <<<"$cfg" local ok=0 fails=() rss=() for r in $(seq 1 "$RUNS"); do d="$TMP/$tag-$lim-$r" CG_MEM=$((lim*MB)) CG_CPUS=2 run_app "$jh" "$N" "$d" $common $fl >/dev/null 2>&1 h=$(kv "$d/memory-idle.txt" maxHeapMB); [ -n "$h" ] && heap="$h" [ -f "$d/retries" ] && RETRIES=$((RETRIES+1)) out=$(cat "$d/outcome.txt") if [ "$out" = ok ]; then ok=$((ok+1)); rss+=("$(kv "$d/memory.txt" rssMB)"); else fails+=("${out%%(*}"); fi done cell="$ok/$RUNS ok" if [ $ok -gt 0 ]; then cell="$cell rss $(printf '%s\n' "${rss[@]}" | median)MB"; fi if [ ${#fails[@]} -gt 0 ]; then cell="$cell [$(printf '%s\n' "${fails[@]}" | sort | uniq -c | awk '{printf "%s%sx %s",sep,$1,$2; sep=" "}')]"; fi cells+=("$cell") done printf '%-8s %-8s %-30s %-30s %-30s\n' "${lim}MB" "${heap}MB" "${cells[0]}" "${cells[1]}" "${cells[2]}" done echo } # ONLY=75 or ONLY=25 runs one of the two sweeps (each takes about 12 minutes); default is both. ONLY="${ONLY:-both}" echo "# $N products; 2 CPUs; $RUNS runs per cell; rss is the median of the runs that finished" if [ "$ONLY" != 25 ]; then sweep "Heap set to 75% of the container (-XX:MaxRAMPercentage=75)" "-XX:MaxRAMPercentage=75" 400 416 432 448 512 704 fi if [ "$ONLY" != 75 ]; then sweep "Heap left at the JVM default (25% of the container)" "" 1024 1152 1216 1280 1536 2048 fi echo "# runs that needed a startup retry (the JVM never came up, for a reason other than OOM or a kernel kill): $RETRIES" rm -rf "$TMP"