#!/bin/bash
# bench-lumbda-www.sh — serve lumbda.com's docroot from asm-gc
# and bombard it with small-file + large-file requests. Verifies:
#  (a) throughput is viable for real traffic,
#  (b) peak RSS stays bounded under mixed payloads (2.67 MB PDF
#      per request would otherwise blow up without heap-restore),
#  (c) PDF bytes round-trip identically across thousands of
#      requests (no truncation, no partial writes).
set -u
cd "$(dirname "$0")/.."

SMALL_N=${SMALL_N:-5000}
LARGE_N=${LARGE_N:-500}
CONCURRENCY=${CONCURRENCY:-8}
BIN=${BIN:-./asm/lumbda-gc}

declare -a SPAWNED=()
cleanup() {
    for pid in "${SPAWNED[@]}"; do kill -9 "$pid" 2>/dev/null; done
    sleep 0.2
    pkill -9 -u "$USER" -f 'examples/http-static-server' 2>/dev/null || true
}
trap cleanup EXIT INT TERM

make -s -C asm all

ulimit -v 524288

printf "\n═══════════════════════════════════════════════════════\n"
printf "lumbda.com under asm-gc: %s small (/) + %s large (/whitepaper.pdf)\n" "$SMALL_N" "$LARGE_N"
printf "  concurrency %s\n" "$CONCURRENCY"
printf "═══════════════════════════════════════════════════════\n"

"$BIN" < examples/http-static-server.lsp >/dev/null 2>&1 &
pid=$!
SPAWNED+=("$pid")

# Wait for port
for _ in $(seq 1 30); do
    if curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/ 2>/dev/null | grep -q 200; then
        break
    fi
    sleep 0.1
done
if ! kill -0 "$pid" 2>/dev/null; then
    echo "server failed to start"; exit 1
fi

# Verify once that the PDF round-trips byte-identically.
curl -s -o /tmp/bench-pdf-check http://localhost:8080/whitepaper.pdf
if cmp /tmp/bench-pdf-check whitepaper/lumbda-whitepaper.pdf >/dev/null 2>&1; then
    echo "  pdf-integrity: byte-identical ($(wc -c < /tmp/bench-pdf-check) bytes)"
else
    echo "  pdf-integrity: DIFFERS"; exit 1
fi
rm -f /tmp/bench-pdf-check

# Baseline RSS
rss0=$(awk '/^VmRSS:/ {print $2}' /proc/$pid/status)
echo "  baseline_rss_kb=$rss0"

# Drive small-file traffic, sample RSS while it runs.
peak=0
t0=$(date +%s.%N)
( seq 1 "$SMALL_N" | xargs -P "$CONCURRENCY" -I_ \
    curl -s -o /dev/null http://localhost:8080/ ) &
curl_pid=$!
while kill -0 "$curl_pid" 2>/dev/null; do
    rss=$(awk '/^VmRSS:/ {print $2}' /proc/$pid/status 2>/dev/null || echo 0)
    [ "$rss" -gt "$peak" ] && peak=$rss
    sleep 0.2
done
wait "$curl_pid" 2>/dev/null || true
t1=$(date +%s.%N)
small_rps=$(python3 -c "print(f'{$SMALL_N / ((float(\"$t1\") - float(\"$t0\")) if float(\"$t1\") > float(\"$t0\") else 1):.0f}')")
printf "  small (/)          %s req/s  peak_rss_kb=%s\n" "$small_rps" "$peak"

# Reset peak for large-file phase
peak=0
t0=$(date +%s.%N)
( seq 1 "$LARGE_N" | xargs -P "$CONCURRENCY" -I_ \
    curl -s -o /dev/null http://localhost:8080/whitepaper.pdf ) &
curl_pid=$!
while kill -0 "$curl_pid" 2>/dev/null; do
    rss=$(awk '/^VmRSS:/ {print $2}' /proc/$pid/status 2>/dev/null || echo 0)
    [ "$rss" -gt "$peak" ] && peak=$rss
    sleep 0.2
done
wait "$curl_pid" 2>/dev/null || true
t1=$(date +%s.%N)
large_rps=$(python3 -c "print(f'{$LARGE_N / ((float(\"$t1\") - float(\"$t0\")) if float(\"$t1\") > float(\"$t0\") else 1):.0f}')")
large_mib=$(python3 -c "print(f'{$LARGE_N * 2669058 / (1024 * 1024) / ((float(\"$t1\") - float(\"$t0\")) if float(\"$t1\") > float(\"$t0\") else 1):.0f}')")
printf "  large (/pdf 2.67M) %s req/s  %s MiB/s  peak_rss_kb=%s\n" "$large_rps" "$large_mib" "$peak"

# Final RSS before kill
final=$(awk '/^VmRSS:/ {print $2}' /proc/$pid/status 2>/dev/null || echo 0)
growth=$((final - rss0))
printf "  final_rss_kb=%s  growth_kb=%s\n" "$final" "$growth"

kill -9 "$pid" 2>/dev/null
wait "$pid" 2>/dev/null || true

if pgrep -u "$USER" -f 'examples/http-static-server' > /dev/null; then
    echo "STRAGGLER" >&2; exit 1
fi
