Files

80 lines
4.0 KiB
Bash

#!/usr/bin/env bash
# Regenerates every file in docs/output/ from a clean build. Run from the repo root.
#
# Requires: GraalVM for JDK 25 on PATH (JAVA_HOME pointing at it), Maven, Python 3.
# Builds JVM jars first, benchmarks them, then builds native images (slow - budget
# 20-30 minutes total on a 2-vCPU machine) and benchmarks those too.
#
# This is exactly the sequence used to produce the committed docs/output/ files -
# re-run it yourself and your numbers should land in the same ballpark, modulo your
# own hardware. See README.md for the one GraalVM build-arg fix the Micronaut module
# needed and why.
set -euo pipefail
cd "$(dirname "$0")/.."
echo "== 1/4: building JVM artifacts =="
(cd spring-boot-app && mvn -q -B clean package -DskipTests)
(cd quarkus-app && mvn -q -B clean package -DskipTests)
(cd micronaut-app && mvn -q -B clean package -DskipTests)
echo "== 2/4: JVM startup + memory (4 runs each, first discarded) =="
{
echo "=== Spring Boot JVM startup+memory (4 runs) ==="
python3 scripts/measure.py "spring-boot-jvm" 8081 /widgets 4 -- java -jar spring-boot-app/target/spring-boot-app.jar
echo "=== Quarkus JVM startup+memory (4 runs) ==="
python3 scripts/measure.py "quarkus-jvm" 8082 /widgets 4 -- java -jar quarkus-app/target/quarkus-app/quarkus-run.jar
echo "=== Micronaut JVM startup+memory (4 runs) ==="
python3 scripts/measure.py "micronaut-jvm" 8083 /widgets 4 -- java -jar micronaut-app/target/micronaut-app.jar
} | tee docs/output/01-startup-memory-jvm.txt
echo "== 3/4: JVM throughput (15s @ concurrency 20, one app at a time) =="
run_throughput() {
local label="$1" port="$2" ready_path="$3"; shift 3
"$@" > "/tmp/${label}.log" 2>&1 < /dev/null &
local pid=$!
disown
for i in $(seq 1 60); do
code=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:${port}${ready_path}" --max-time 2 || true)
[ "$code" = "200" ] && break
sleep 0.2
done
python3 scripts/throughput.py "$label" localhost "$port" "$ready_path" 15 20
kill -9 "$pid" 2>/dev/null || true
sleep 1
}
{
echo "=== Spring Boot JVM throughput ==="
run_throughput spring-boot-jvm 8081 /widgets java -jar spring-boot-app/target/spring-boot-app.jar
echo "=== Quarkus JVM throughput ==="
run_throughput quarkus-jvm 8082 /widgets java -jar quarkus-app/target/quarkus-app/quarkus-run.jar
echo "=== Micronaut JVM throughput ==="
run_throughput micronaut-jvm 8083 /widgets java -jar micronaut-app/target/micronaut-app.jar
} | tee docs/output/02-throughput-jvm.txt
echo "== 4/4: native builds + benchmarks (slow) =="
(cd quarkus-app && mvn -q -B -Pnative clean package -DskipTests && mvn -q -B package -DskipTests)
(cd micronaut-app && mvn -q -B -Pnative clean package -DskipTests && \
mvn -q -B -Pnative package org.graalvm.buildtools:native-maven-plugin:compile -DskipTests)
(cd spring-boot-app && mvn -q -B -Pnative clean package -DskipTests && mvn -q -B -Pnative native:compile)
{
echo "=== Spring Boot NATIVE startup+memory (4 runs) ==="
python3 scripts/measure.py "spring-boot-native" 8081 /widgets 4 -- ./spring-boot-app/target/spring-boot-app
echo "=== Quarkus NATIVE startup+memory (4 runs) ==="
python3 scripts/measure.py "quarkus-native" 8082 /widgets 4 -- ./quarkus-app/target/quarkus-app-runner
echo "=== Micronaut NATIVE startup+memory (4 runs) ==="
python3 scripts/measure.py "micronaut-native" 8083 /widgets 4 -- ./micronaut-app/target/micronaut-app
} | tee docs/output/03-startup-memory-native.txt
{
echo "=== Spring Boot NATIVE throughput ==="
run_throughput spring-boot-native 8081 /widgets ./spring-boot-app/target/spring-boot-app
echo "=== Quarkus NATIVE throughput ==="
run_throughput quarkus-native 8082 /widgets ./quarkus-app/target/quarkus-app-runner
echo "=== Micronaut NATIVE throughput ==="
run_throughput micronaut-native 8083 /widgets ./micronaut-app/target/micronaut-app
} | tee docs/output/04-throughput-native.txt
echo "Done. See docs/output/05-summary.txt for the consolidated table (written by hand from the runs above - update it if your numbers differ materially)."