New infra:
- examples/http-server-noarena.lsp: same HTTP server minus the
heap-snapshot/heap-restore arena loop. Isolates whether the GC
build actually holds memory under real traffic, independent
of the portable snapshot pattern.
- tests/bench-gc-http.sh: drives 5,000 concurrent requests per
cell across the full 2x2 matrix {no-GC, GC} x {snapshot, no}.
- Makefile: new `bench-gc-http` target.
Extended benches to exercise both asm binaries:
- tests/bench-hashset.sh now runs against both asm/uncommonlisp
and asm/uncommonlisp-gc, with set +e so a GC-build crash on
one workload doesn't abort the other.
- tests/web-benchmark.sh adds a dedicated asm-gc row (and prints
its stripped binary size) so the HTTP throughput comparison
reports both.
Whitepaper updates:
- §6.6.4 "Validation: HTTP Server Under Sustained Load" — the
4-cell memory matrix. 3/4 cells green; cell 4 (GC + no
snapshot) crashes at first GC trigger — another instance of
the conservative-scan type-confusion class we already fixed
once at the env/string boundary. Logged as a known issue
rather than shipping a partial fix under time pressure.
heap-snapshot + heap-restore remains the recommended pattern
for production asm code; the naive GC is diagnostic + control
group, not a replacement for the arena discipline.
- §6.5 hash-set speedup table slightly softened to ~15-20x (was
15-21x) since run-to-run noise on a shared laptop shifts the
per-phase ratio by a few percent. Ratio is stable to first
order.
- §8.6 narrative references the ~1280x symbolic-vs-brute-force
figure instead of the stale 40x.
- §6 reproducibility list now lists `make bench-gc-http`.
All 137 asm no-GC + 137 asm GC + 189 shared functional tests
still pass.
30 lines
1.1 KiB
Bash
Executable file
30 lines
1.1 KiB
Bash
Executable file
#!/bin/bash
|
|
# bench-hashset.sh — run the asm native hash-set vs portable benchmark
|
|
# and echo the speedup. ASM-only: C/Python have no hash-set builtin.
|
|
set +e
|
|
cd "$(dirname "$0")/.."
|
|
|
|
ulimit -v 524288
|
|
trap 'pkill -9 -u "$USER" -f "asm/uncommonlisp" 2>/dev/null || true' EXIT
|
|
|
|
# Build if needed
|
|
if [ ! -x asm/uncommonlisp ] || [ asm/uncommonlisp.s -nt asm/uncommonlisp ]; then
|
|
make -s asm-build
|
|
fi
|
|
|
|
echo "── asm no-GC ──"
|
|
timeout 60 ./asm/uncommonlisp < examples/bench-hashset.lsp
|
|
echo ""
|
|
echo "── asm GC (GC_NAIVE build) ──"
|
|
# Under GC_NAIVE the heap is 1 MB per chunk; build-list(K=500) runs
|
|
# into the bump threshold and triggers implicit GC. That's the
|
|
# intended comparison — same primitives, different allocator.
|
|
timeout 60 ./asm/uncommonlisp-gc < examples/bench-hashset.lsp
|
|
|
|
# Verify cleanup. pgrep with -x matches the exact command basename
|
|
# so it doesn't false-positive on the parent shell.
|
|
if pgrep -u "$USER" -x uncommonlisp > /dev/null || \
|
|
pgrep -u "$USER" -x uncommonlisp-gc > /dev/null; then
|
|
echo "STRAGGLER asm binary detected" >&2
|
|
exit 1
|
|
fi
|