Skip to content

Commit 0d4def4

Browse files
committed
refactor(server): remove benchmark-mode in favor of production preload
--benchmark-mode produced identical throughput (~76k req/sec) to --preload --gc-percent 400 in bare-metal benchmarks. Remove the dedicated minimal handler, its tests, all CLI flag wiring, and the benchmark-mode test from baremetal.sh. The production preload path is now the single optimised configuration.
1 parent 9a8bf21 commit 0d4def4

File tree

4 files changed

+25
-428
lines changed

4 files changed

+25
-428
lines changed

benchmark/baremetal.sh

Lines changed: 22 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
# =============================================================================
33
# baremetal.sh — Bare-metal benchmark: static-web vs Bun
44
#
5-
# Builds static-web from source, benchmarks three configurations on the same
6-
# port one at a time, then prints a ranked comparison. No Docker.
5+
# Builds static-web from source, benchmarks two servers on the same port one
6+
# at a time, then prints a head-to-head comparison. No Docker.
77
#
88
# Configurations tested:
9-
# 1. static-web --benchmark-mode (minimal handler, zero overhead)
10-
# 2. static-web --preload --gc-percent 400 (production optimised)
11-
# 3. Bun native static HTML server
9+
# 1. static-web --preload --gc-percent 400 (production optimised)
10+
# 2. Bun native static HTML server
1211
#
1312
# Usage:
1413
# ./benchmark/baremetal.sh [OPTIONS]
@@ -173,18 +172,18 @@ main() {
173172

174173
local URL="http://localhost:${PORT}/index.html"
175174

176-
# Result arrays (indexed: 0=benchmark-mode, 1=preload, 2=bun)
175+
# Result arrays (indexed: 0=preload, 1=bun)
177176
local -a NAMES RPS_ARR P50_ARR P99_ARR TP_ARR
178-
NAMES=("static-web (benchmark-mode)" "static-web (preload+gc400)" "Bun")
177+
NAMES=("static-web (preload+gc400)" "Bun")
179178

180179
# ======================================================================
181-
# Test 1: static-web --benchmark-mode (minimal handler)
180+
# Test 1: static-web --preload --gc-percent 400 (production mode)
182181
# ======================================================================
183182
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
184-
echo -e "${BOLD} [ static-web — benchmark mode (minimal handler) ]${RESET}"
183+
echo -e "${BOLD} [ static-web — production: --preload --gc-percent 400 ]${RESET}"
185184
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
186185

187-
"$BIN" --benchmark-mode --port "$PORT" "$abs_root" &
186+
"$BIN" --quiet --no-compress --preload --gc-percent 400 --port "$PORT" "$abs_root" &
188187
SERVER_PID=$!
189188
sleep "$SETTLE_SECONDS"
190189
wait_for_port "$PORT"
@@ -197,7 +196,7 @@ main() {
197196

198197
echo -e " ${CYAN}Benchmarking...${RESET}"
199198
local raw
200-
raw=$(run_bombardier "$URL" | tee "${RESULTS_DIR}/baremetal-static-web-benchmark.txt")
199+
raw=$(run_bombardier "$URL" | tee "${RESULTS_DIR}/baremetal-static-web-preload.txt")
201200
echo ""
202201

203202
RPS_ARR[0]=$(echo "$raw" | parse_rps)
@@ -211,13 +210,13 @@ main() {
211210
kill_on_port "$PORT"
212211

213212
# ======================================================================
214-
# Test 2: static-web --preload --gc-percent 400 (production mode)
213+
# Test 2: Bun static serve
215214
# ======================================================================
216215
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
217-
echo -e "${BOLD} [ static-webproduction: --preload --gc-percent 400 ]${RESET}"
216+
echo -e "${BOLD} [ Bunnative static HTML server ]${RESET}"
218217
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
219218

220-
"$BIN" --quiet --no-compress --preload --gc-percent 400 --port "$PORT" "$abs_root" &
219+
(cd "$abs_root" && bun --port "$PORT" ./index.html) &
221220
SERVER_PID=$!
222221
sleep "$SETTLE_SECONDS"
223222
wait_for_port "$PORT"
@@ -229,7 +228,7 @@ main() {
229228
sleep "$SETTLE_SECONDS"
230229

231230
echo -e " ${CYAN}Benchmarking...${RESET}"
232-
raw=$(run_bombardier "$URL" | tee "${RESULTS_DIR}/baremetal-static-web-preload.txt")
231+
raw=$(run_bombardier "$URL" | tee "${RESULTS_DIR}/baremetal-bun.txt")
233232
echo ""
234233

235234
RPS_ARR[1]=$(echo "$raw" | parse_rps)
@@ -239,61 +238,14 @@ main() {
239238

240239
kill "$SERVER_PID" 2>/dev/null; wait "$SERVER_PID" 2>/dev/null || true
241240
SERVER_PID=""
242-
sleep 1
243-
kill_on_port "$PORT"
244241

245242
# ======================================================================
246-
# Test 3: Bun static serve
243+
# Rank results (descending by RPS — simple swap for 2 elements)
247244
# ======================================================================
248-
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
249-
echo -e "${BOLD} [ Bun — native static HTML server ]${RESET}"
250-
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
251-
252-
(cd "$abs_root" && bun --port "$PORT" ./index.html) &
253-
SERVER_PID=$!
254-
sleep "$SETTLE_SECONDS"
255-
wait_for_port "$PORT"
256-
echo -e " ${GREEN}Server ready (PID ${SERVER_PID})${RESET}"
257-
258-
echo -e " ${DIM}Warming up (${WARMUP_REQUESTS} requests)...${RESET}"
259-
bombardier -c "$CONNECTIONS" -n "$WARMUP_REQUESTS" --print i "$URL" >/dev/null 2>&1
260-
echo -e " ${DIM}Settle (${SETTLE_SECONDS}s)...${RESET}"
261-
sleep "$SETTLE_SECONDS"
262-
263-
echo -e " ${CYAN}Benchmarking...${RESET}"
264-
raw=$(run_bombardier "$URL" | tee "${RESULTS_DIR}/baremetal-bun.txt")
265-
echo ""
266-
267-
RPS_ARR[2]=$(echo "$raw" | parse_rps)
268-
P50_ARR[2]=$(echo "$raw" | parse_p50)
269-
P99_ARR[2]=$(echo "$raw" | parse_p99)
270-
TP_ARR[2]=$(echo "$raw" | parse_tp)
271-
272-
kill "$SERVER_PID" 2>/dev/null; wait "$SERVER_PID" 2>/dev/null || true
273-
SERVER_PID=""
274-
275-
# ======================================================================
276-
# Rank results (descending by RPS — insertion sort, 3 elements)
277-
# ======================================================================
278-
local -a SORTED_IDX=(0 1 2)
279-
local n=3 i=1
280-
while [ $i -lt $n ]; do
281-
local key_idx=${SORTED_IDX[$i]}
282-
local key_rps=${RPS_ARR[$key_idx]}
283-
local j=$((i - 1))
284-
while [ $j -ge 0 ]; do
285-
local cmp_idx=${SORTED_IDX[$j]}
286-
local cmp_rps=${RPS_ARR[$cmp_idx]}
287-
if awk "BEGIN{exit !($cmp_rps < $key_rps)}" 2>/dev/null; then
288-
SORTED_IDX[$((j + 1))]=${SORTED_IDX[$j]}
289-
j=$((j - 1))
290-
else
291-
break
292-
fi
293-
done
294-
SORTED_IDX[$((j + 1))]=$key_idx
295-
i=$((i + 1))
296-
done
245+
local -a SORTED_IDX=(0 1)
246+
if awk "BEGIN{exit !(${RPS_ARR[1]} > ${RPS_ARR[0]})}" 2>/dev/null; then
247+
SORTED_IDX=(1 0)
248+
fi
297249

298250
# ======================================================================
299251
# Print results table
@@ -311,10 +263,8 @@ main() {
311263
local colour medal
312264
if [ "$rank" -eq 1 ]; then
313265
colour="$GREEN"; medal="1st"
314-
elif [ "$rank" -eq 2 ]; then
315-
colour="$YELLOW"; medal="2nd"
316266
else
317-
colour="$RESET"; medal="3rd"
267+
colour="$YELLOW"; medal="2nd"
318268
fi
319269

320270
printf "${colour}║ %-4s %-30s %10s %8s %8s ║${RESET}\n" \
@@ -325,9 +275,8 @@ main() {
325275
echo -e "${BOLD}╚════════════════════════════════════════════════════════════════════╝${RESET}"
326276
echo ""
327277
echo -e " ${DIM}Throughput:${RESET}"
328-
echo -e " ${DIM} benchmark-mode ${TP_ARR[0]}${RESET}"
329-
echo -e " ${DIM} preload+gc400 ${TP_ARR[1]}${RESET}"
330-
echo -e " ${DIM} Bun ${TP_ARR[2]}${RESET}"
278+
echo -e " ${DIM} preload+gc400 ${TP_ARR[0]}${RESET}"
279+
echo -e " ${DIM} Bun ${TP_ARR[1]}${RESET}"
331280
echo -e " ${DIM}Results saved to: ${RESULTS_DIR}/baremetal-*.txt${RESET}"
332281
echo ""
333282
}

cmd/static-web/main.go

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ func runServe(args []string) {
100100

101101
// Compression.
102102
noCompress := fs.Bool("no-compress", false, "disable response compression")
103-
benchmarkMode := fs.Bool("benchmark-mode", false, "serve files via a minimal benchmark-oriented handler")
104103

105104
// Security.
106105
cors := fs.String("cors", "", "allowed CORS origins, comma-separated or * for all")
@@ -123,9 +122,6 @@ func runServe(args []string) {
123122
effectivePort = *port
124123
}
125124
effectiveQuiet := *quiet || *quietLong
126-
if *benchmarkMode {
127-
effectiveQuiet = true
128-
}
129125

130126
// Load configuration (defaults → config file → env vars).
131127
cfg, err := config.Load(*cfgPath)
@@ -154,7 +150,6 @@ func runServe(args []string) {
154150
preload: *preload,
155151
gcPercent: *gcPercent,
156152
noCompress: *noCompress,
157-
benchmarkMode: *benchmarkMode,
158153
cors: *cors,
159154
dirListing: *dirListing,
160155
noDotfileBlock: *noDotfileBlock,
@@ -171,15 +166,7 @@ func runServe(args []string) {
171166
if !effectiveQuiet {
172167
log.Printf("static-web %s starting (addr=%s, root=%s)", version.Version, cfg.Server.Addr, cfg.Files.Root)
173168
}
174-
if *benchmarkMode {
175-
log.Printf("benchmark mode enabled: cache, compression, TLS redirect, custom 404, security middleware, and extra headers are bypassed")
176-
// Reduce GC frequency — in benchmark mode the handler is
177-
// allocation-free so there is very little garbage, but net/http
178-
// internals still allocate per-request. A higher GOGC lets those
179-
// short-lived objects be collected in bulk, cutting GC pause
180-
// overhead by ~10%.
181-
debug.SetGCPercent(400)
182-
} else if cfg.Cache.GCPercent > 0 {
169+
if cfg.Cache.GCPercent > 0 {
183170
old := debug.SetGCPercent(cfg.Cache.GCPercent)
184171
if !effectiveQuiet {
185172
log.Printf("GC target set to %d%% (was %d%%)", cfg.Cache.GCPercent, old)
@@ -188,7 +175,7 @@ func runServe(args []string) {
188175

189176
// Initialise the in-memory file cache (respects cfg.Cache.Enabled).
190177
var c *cache.Cache
191-
if cfg.Cache.Enabled && !*benchmarkMode {
178+
if cfg.Cache.Enabled {
192179
c = cache.NewCache(cfg.Cache.MaxBytes, cfg.Cache.TTL)
193180
} else {
194181
c = nil
@@ -222,21 +209,14 @@ func runServe(args []string) {
222209

223210
// Build the full middleware + handler chain.
224211
var h http.Handler
225-
if *benchmarkMode {
226-
h = handler.BuildBenchmarkHandler(cfg)
227-
} else if effectiveQuiet {
212+
if effectiveQuiet {
228213
h = handler.BuildHandlerQuiet(cfg, c, pathCache)
229214
} else {
230215
h = handler.BuildHandler(cfg, c, pathCache)
231216
}
232217

233218
// Create the HTTP/HTTPS server.
234219
serverCfg := cfg.Server
235-
if *benchmarkMode {
236-
serverCfg.TLSCert = ""
237-
serverCfg.TLSKey = ""
238-
serverCfg.RedirectHost = ""
239-
}
240220
srv := server.New(&serverCfg, &cfg.Security, h)
241221

242222
// Start listeners in the background.
@@ -266,7 +246,6 @@ type flagOverrides struct {
266246
preload bool
267247
gcPercent int
268248
noCompress bool
269-
benchmarkMode bool
270249
cors string
271250
dirListing bool
272251
noDotfileBlock bool
@@ -324,19 +303,6 @@ func applyFlagOverrides(cfg *config.Config, f flagOverrides) error {
324303
if f.gcPercent != 0 {
325304
cfg.Cache.GCPercent = f.gcPercent
326305
}
327-
if f.benchmarkMode {
328-
cfg.Cache.Enabled = false
329-
cfg.Compression.Enabled = false
330-
cfg.Files.NotFound = ""
331-
cfg.Security.BlockDotfiles = false
332-
cfg.Security.DirectoryListing = false
333-
cfg.Security.CORSOrigins = nil
334-
cfg.Security.CSP = ""
335-
cfg.Security.ReferrerPolicy = ""
336-
cfg.Security.PermissionsPolicy = ""
337-
cfg.Security.HSTSMaxAge = 0
338-
cfg.Security.HSTSIncludeSubdomains = false
339-
}
340306
if f.cacheSize != "" {
341307
n, err := parseBytes(f.cacheSize)
342308
if err != nil {
@@ -543,7 +509,6 @@ Serve flags:
543509
--preload preload all files into cache at startup
544510
--gc-percent int set Go GC target %% (0=default, 400 for high throughput)
545511
--no-compress disable response compression
546-
--benchmark-mode serve files via a minimal benchmark-oriented handler
547512
--cors string CORS origins, comma-separated or * for all
548513
--dir-listing enable directory listing
549514
--no-dotfile-block disable dotfile blocking

0 commit comments

Comments
 (0)