Three defects fixed today on the asm tier worker path:
1. Multi-line "..." docstrings crashed asm tier's scheme_read.
wire.lsp, bend.lsp, gpu-worker.lsp had docstrings spanning
several lines; replaced with ;; comments before each define.
asm tier loads these cleanly now.
2. asm tier lacked delete-file. handle-cuda-shake-fanout called
it to clean up temp portal files. Added bi_delete_file via
SYS_UNLINK = 87 syscall (~20 LoC asm). BI_DELETEFILE constant
slotted after sibling-agent's BI_STRTOSYM.
3. All Scheme files in examples/cuda-fanout/ now ASCII-only.
Earlier em-dash / × / → / μ tripped asm tier's reader in
subtle ways during file load. iconv pass + sed fixes.
Result: all three tiers complete the bench through their own
cliff. New 3-tier table:
workload Python C tier asm tier
small (3 × 16 B) 1.27 ms 0.16 ms 0.21 ms
small (100 × 16 B) 3.43 ms 0.40 ms 1.99 ms
medium (1000) 23.24 ms 2.77 ms CLIFF
med (10k) 218.82 ms CLIFF CLIFF
huge (50k) 1,099 ms CLIFF CLIFF
huge (100k) 2,219 ms CLIFF CLIFF
huge (1M) 23,811 ms CLIFF CLIFF
asm tier at 0.21 ms beats Python by 6× at smallest workload,
matches C at the bottom (~30% slower). asm cliffs at 1000;
C tier cliffs at 10k. Both cliffs are reader/buffer limits
inside the tier, not network or kernel. CUDA kernel itself
finishes 1M × 16B in ~47 ms — three orders of magnitude under
any tier's wire cost at huge scale.
bench_tiers.py made cliff-resilient: respawns worker on per-
workload failure & continues, so the full row prints for every
tier instead of bailing on first cliff.
www/index.html: full 3-column table + honest framing of when
each tier earns its slot.