Skip to content

Commit bba428c

Browse files
brunoborgesCopilot
andcommitted
Add Phase 3: CI cold-start benchmark (no caches)
Simulates fresh CI runner: clears __pycache__ and JBang cache, then measures single cold run for each method. Shows the true value of AOT in CI where Python has no bytecode cache. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 83336d5 commit bba428c

File tree

3 files changed

+78
-7
lines changed

3 files changed

+78
-7
lines changed

.github/workflows/benchmark.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ jobs:
7474
JAR_STEADY=$(avg_runs $STEADY_RUNS java -jar "$JAR")
7575
AOT_STEADY=$(avg_runs $STEADY_RUNS java -XX:AOTCache="$AOT" -jar "$JAR")
7676
77+
# --- Phase 3: CI cold start (no caches, simulates fresh runner) ---
78+
find html-generators -name '__pycache__' -type d -exec rm -rf {} + 2>/dev/null || true
79+
PY_CI=$(measure python3 html-generators/generate.py)
80+
81+
jbang cache clear > /dev/null 2>&1 || true
82+
JBANG_CI=$(measure jbang html-generators/generate.java)
83+
84+
JAR_CI=$(measure java -jar "$JAR")
85+
AOT_CI=$(measure java -XX:AOTCache="$AOT" -jar "$JAR")
86+
7787
# Write to GitHub Actions Job Summary
7888
{
7989
echo "## Benchmark Results — \`$os_name\`"
@@ -96,4 +106,17 @@ jobs:
96106
echo "| **Fat JAR** | ${JAR_STEADY}s |"
97107
echo "| **JBang** | ${JBANG_STEADY}s |"
98108
echo "| **Python** | ${PY_STEADY}s |"
109+
echo ""
110+
echo "### Phase 3: CI Cold Start (fresh runner, no caches)"
111+
echo ""
112+
echo "Simulates a CI environment where every run is the first run."
113+
echo "Python has no \`__pycache__\`, JBang has no compilation cache."
114+
echo "Java AOT benefits from the pre-built \`.aot\` file restored from actions cache."
115+
echo ""
116+
echo "| Method | Time |"
117+
echo "|--------|------|"
118+
echo "| **Fat JAR + AOT** | **${AOT_CI}s** |"
119+
echo "| **Fat JAR** | ${JAR_CI}s |"
120+
echo "| **JBang** | ${JBANG_CI}s |"
121+
echo "| **Python** | ${PY_CI}s |"
99122
} >> "$GITHUB_STEP_SUMMARY"

html-generators/benchmark/README.md

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,33 @@ These are one-time setup costs, comparable across languages.
88

99
| Step | Time | What it does |
1010
|------|------|-------------|
11-
| Python first run | 2.34s | Interprets source, creates `__pycache__` bytecode |
12-
| JBang export | 2.92s | Compiles source + bundles dependencies into fat JAR |
13-
| AOT training run | 3.14s | Runs JAR once to record class loading, produces `.aot` cache |
11+
| Python first run | 1.98s | Interprets source, creates `__pycache__` bytecode |
12+
| JBang export | 2.19s | Compiles source + bundles dependencies into fat JAR |
13+
| AOT training run | 2.92s | Runs JAR once to record class loading, produces `.aot` cache |
1414

1515
## Phase 2: Steady-State Execution (avg of 5 runs)
1616

1717
After one-time setup, these are the per-run execution times.
1818

1919
| Method | Avg Time | Notes |
2020
|--------|---------|-------|
21-
| **Fat JAR + AOT** | **0.35s** | Fastest; pre-loaded classes from AOT cache |
22-
| **Fat JAR** | 0.50s | JVM class loading on every run |
23-
| **JBang** | 1.19s | Includes JBang launcher overhead |
24-
| **Python** | 1.37s | Uses cached `__pycache__` bytecode |
21+
| **Fat JAR + AOT** | **0.32s** | Fastest; pre-loaded classes from AOT cache |
22+
| **Fat JAR** | 0.44s | JVM class loading on every run |
23+
| **JBang** | 1.08s | Includes JBang launcher overhead |
24+
| **Python** | 1.26s | Uses cached `__pycache__` bytecode |
25+
26+
## Phase 3: CI Cold Start (fresh runner, no caches)
27+
28+
Simulates a CI environment where every run is the first run.
29+
Python has no `__pycache__`, JBang has no compilation cache.
30+
Java AOT benefits from the pre-built `.aot` file restored from actions cache.
31+
32+
| Method | Time | Notes |
33+
|--------|------|-------|
34+
| **Fat JAR + AOT** | **0.46s** | AOT cache ships pre-loaded classes |
35+
| **Fat JAR** | 0.40s | JVM class loading from scratch |
36+
| **JBang** | 3.25s | Must compile source before running |
37+
| **Python** | 0.16s | No `__pycache__`; full interpretation |
2538

2639
## How It Works
2740

html-generators/benchmark/run.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,28 @@ echo " Fat JAR + AOT: ${AOT_STEADY}s"
113113

114114
echo ""
115115

116+
# ---------------------------------------------------------------------------
117+
# Phase 3: CI cold start (no caches, simulates fresh runner)
118+
# ---------------------------------------------------------------------------
119+
echo "=== Phase 3: CI Cold Start (fresh runner, no caches) ==="
120+
echo ""
121+
122+
find html-generators -name '__pycache__' -type d -exec rm -rf {} + 2>/dev/null || true
123+
PY_CI=$(measure python3 html-generators/generate.py)
124+
echo " Python (no __pycache__): ${PY_CI}s"
125+
126+
jbang cache clear > /dev/null 2>&1 || true
127+
JBANG_CI=$(measure jbang html-generators/generate.java)
128+
echo " JBang (no cache): ${JBANG_CI}s"
129+
130+
JAR_CI=$(measure java -jar "$JAR")
131+
echo " Fat JAR: ${JAR_CI}s"
132+
133+
AOT_CI=$(measure java -XX:AOTCache="$AOT" -jar "$JAR")
134+
echo " Fat JAR + AOT: ${AOT_CI}s"
135+
136+
echo ""
137+
116138
# ---------------------------------------------------------------------------
117139
# Optionally update README.md
118140
# ---------------------------------------------------------------------------
@@ -144,6 +166,19 @@ After one-time setup, these are the per-run execution times.
144166
| **JBang** | ${JBANG_STEADY}s | Includes JBang launcher overhead |
145167
| **Python** | ${PY_STEADY}s | Uses cached \`__pycache__\` bytecode |
146168
169+
## Phase 3: CI Cold Start (fresh runner, no caches)
170+
171+
Simulates a CI environment where every run is the first run.
172+
Python has no \`__pycache__\`, JBang has no compilation cache.
173+
Java AOT benefits from the pre-built \`.aot\` file restored from actions cache.
174+
175+
| Method | Time | Notes |
176+
|--------|------|-------|
177+
| **Fat JAR + AOT** | **${AOT_CI}s** | AOT cache ships pre-loaded classes |
178+
| **Fat JAR** | ${JAR_CI}s | JVM class loading from scratch |
179+
| **JBang** | ${JBANG_CI}s | Must compile source before running |
180+
| **Python** | ${PY_CI}s | No \`__pycache__\`; full interpretation |
181+
147182
## How It Works
148183
149184
- **Python** caches compiled bytecode in \`__pycache__/\` after the first run, similar to how Java's AOT cache works.

0 commit comments

Comments
 (0)