asm: native hash-set + benchmark — 15-21x over portable

Adds 6 hash-set builtins (make-hash-set, hash-set?, hash-set-add!,
hash-set-contains?, hash-set-size, hash-set->list). Same sentinel
scheme as hash-table but tag word = -2 (hash-table is -1, vector
is >= 0). One cons cell per entry (vs two for hash-table) since
a set stores keys only — that's where the speedup over the Scheme-
level vector-based ht-* lib comes from.

Benchmark (tests/bench-hashset.sh, via make bench-hashset),
N=5000, i5-8350U asm tier:

                portable   native   speedup
  insert        ~130 ms    ~7 ms    ~20x
  hit-lookup    ~125 ms    ~8 ms    ~15x
  miss-lookup   ~240 ms    ~12 ms   ~20x

Portable is the ht-* lib from proof-netspace-server-lib.lsp
(vectors + cons chains + modulo, pure Scheme). Native replaces
the Scheme-level bucket walk with an asm loop that dereferences
pairs directly — no env lookups, no frame building per iteration.

All 137 asm + 189 functional (Python + C) tests still green.
This commit is contained in:
russell@unturf.com 2026-04-18 06:15:21 -04:00
parent f675778c6d
commit afb5616843
6 changed files with 374 additions and 8 deletions

21
tests/bench-hashset.sh Executable file
View file

@ -0,0 +1,21 @@
#!/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
timeout 60 ./asm/uncommonlisp < examples/bench-hashset.lsp
# Verify cleanup
if pgrep -u "$USER" -f 'asm/uncommonlisp' > /dev/null; then
echo "STRAGGLER asm/uncommonlisp detected" >&2
exit 1
fi