#!/usr/bin/env bash # Startup and first-request latency for every configuration. Configurations are run in interleaved rounds # (round 1 runs all of them once, then round 2, ...) so slow drift on a shared machine hits all of them alike. # scripts/startup.sh [ROUNDS] default 10 source "$(dirname "$0")/lib.sh" ROUNDS=${1:-10} LOG="$WORK/startup-runs.txt"; : > "$LOG" declare -A WD CMD labels=() add_cfg() { local l=$1 wd=$2; shift 2; labels+=("$l"); WD[$l]=$wd; CMD[$l]="$*"; } J25=$JDK25/bin/java; J27=$JDK27/bin/java add_cfg "1 jvm-fat-jar" "$WORK" "$J25 -jar app.jar" add_cfg "2 jvm-extracted" "$WORK/ext" "$J25 -jar app.jar" add_cfg "3 jvm+spring-aot" "$WORK/ext-springaot" "$J25 -Dspring.aot.enabled=true -jar app.jar" add_cfg "4 appcds" "$WORK/ext" "$J25 -XX:SharedArchiveFile=$WORK/appcds.jsa -jar app.jar" add_cfg "5 aot-cache fat-jar" "$WORK" "$J25 -XX:AOTCache=$WORK/fat.aot -jar app.jar" add_cfg "6 aot-cache context-only" "$WORK/ext" "$J25 -XX:AOTCache=$WORK/refresh.aot -jar app.jar" add_cfg "7 aot-cache traffic" "$WORK/ext" "$J25 -XX:AOTCache=$WORK/traffic.aot -jar app.jar" add_cfg "8 aot-cache+spring-aot" "$WORK/ext-springaot" "$J25 -Dspring.aot.enabled=true -XX:AOTCache=$WORK/springaot.aot -jar app.jar" add_cfg "9 aot-cache+spring-aot traffic" "$WORK/ext-springaot" "$J25 -Dspring.aot.enabled=true -XX:AOTCache=$WORK/springaot-traffic.aot -jar app.jar" add_cfg "10 jdk27 plain" "$WORK/ext" "$J27 -jar app.jar" add_cfg "11 jdk27 aot-cache" "$WORK/ext" "$J27 -XX:AOTCache=$WORK/refresh27.aot -jar app.jar" [ -x "$WORK/aot-cache-native" ] && add_cfg "12 native image" "$WORK" "$WORK/aot-cache-native" one_run() { # label round local l=$1 r=$2 t0 ready started first second med50 rss t0=$(now_ms) start_app "${WD[$l]}" "$WORK/run.log" ${CMD[$l]} --server.port=$PORT if ! wait_ready; then echo "RUN|$l|$r|FAILED" >> "$LOG"; stop_app; return; fi ready=$(( $(now_ms) - t0 )) started=$(grep -o 'Started [A-Za-z]* in [0-9.]* seconds' "$WORK/run.log" | awk '{print $4*1000}') first=$(post_order); second=$(get_order) med50=$(for i in $(seq 1 50); do post_order; echo; done | grep . | median) rss=$(rss_mb) echo "RUN|$l|$r|ready=$ready|started=${started:-n/a}|first=$first|second=$second|next50=$med50|rss=$rss" >> "$LOG" stop_app; sleep 0.5 } echo "# ${#labels[@]} configurations x $ROUNDS rounds; one unrecorded warm-up round first (so cache files are in the page cache)" for l in "${labels[@]}"; do one_run "$l" 0; done; : > "$LOG" for r in $(seq 1 $ROUNDS); do for l in "${labels[@]}"; do one_run "$l" "$r"; done echo "round $r done" >&2 done field() { grep -F "RUN|$1|" "$LOG" | grep -o "$2=[0-9.]*" | cut -d= -f2; } echo echo "== medians of $ROUNDS runs (min..max in brackets), milliseconds; rss in MB" printf '%-32s %-20s %-20s %-20s %-18s %s\n' "configuration" "ready (exec->200)" "Boot 'Started in'" "1st POST /orders" "next 50 (median)" "RSS" for l in "${labels[@]}"; do f=$(grep -cF "RUN|$l|" "$LOG"); ok=$(grep -F "RUN|$l|" "$LOG" | grep -vc FAILED) cell() { local v; v=$(field "$l" "$1"); printf '%-20s ' "$(echo "$v" | median) [$(echo "$v" | minmax)]"; } printf '%-32s ' "$l"; cell ready; cell started; cell first; printf '%-18s ' "$(field "$l" next50 | median)"; printf '%s' "$(field "$l" rss | median)" [ "$ok" != "$f" ] && printf ' (%s of %s runs failed)' $((f-ok)) $f echo done echo echo "== every run" sed 's/^RUN|//; s/|/ /g' "$LOG"