Page maps handled removal with tombstones, which a fixed-capacity map
can never outgrow. Keeping probe lengths bounded required an insertion
headroom counter, an allocation-free rehash, and five separate recovery
paths with subtle invariants: removal created a tombstone without
restoring headroom, so the counter could reach zero while the map was
half empty and every insertion path had to be prepared to rebuild.
Replace tombstones with backward-shift deletion (Knuth vol. 3, 6.4
algorithm R). Removal restores the table to the state it would be in
had the key never been inserted, so probe chains stay canonical at all
times and fragmentation cannot accumulate by construction. This deletes
the headroom counter, the in-place rehash, and every recovery path.
Insertion no longer invalidates pointers; removal may now move other
entries instead, and no caller holds entry pointers across removals.
Removal costs a cluster scan instead of a byte write, paying
incrementally what tombstones deferred to later probes and periodic
rebuilds. Free slots remain all-zero bytes so probe loops keep fusing
the state and fingerprint checks into single-byte compares. A
randomized oracle test against the stdlib map and a canonical-placement
invariant check cover the new removal path, including full tables where
no free slot terminates the shift.
ReleaseFast benchmarks against the prior map commits:
| workload | delta |
|---|---:|
| map churn, 50% load | 1.23x faster |
| map churn, 75% load | 1.15x faster |
| map churn, max load | 1.07x slower |
| map lookup | neutral |
| clear and redraw stream | 1.32x faster |
| full OSC 8 stream | 1.06x faster |
| linked-line movement | neutral |
Hyperlink and grapheme maps are keyed by cell offset. Moving their
data removes the source entry and reinserts it at a destination known
to be absent. Generic clobbering insertion still searches the probe
sequence to rule out a duplicate.
Use no-clobber insertion for these moves so the first available
tombstone can be reused. If a destination reaches a free slot after
tombstones exhaust insertion headroom, rebuild the map in place and
retry before decrementing the budget. This keeps the known-absent fast
path safe at every load state.
The ReleaseFast movement benchmark improves from 133.7 ms to 126.4 ms,
a 5.5% reduction. The linked-line control remains neutral at 395.4 ms
before and 395.7 ms after.
#13292
Page maps previously allowed a 100% load factor. Once live entries
and tombstones filled every slot, a missing-key lookup or insertion
could scan the entire map.
Reserve 20% of each offset hash map as insertion headroom and track
that budget separately from the live count. Port the allocation-free
in-place rehash from Zig HashMapUnmanaged so canonical insertion can
rebuild fragmented probes and restore tombstone-exhausted headroom
without growing the page. Assumed-capacity insertion now applies the
same guard, preventing the headroom counter from wrapping.
Pass the exact requested hyperlink count into map layout before
load-factor scaling, avoiding a redundant power-of-two rounding step.
Screen-level recovery now grows only when live hyperlinks actually fill
usable capacity.
ReleaseFast terminal benchmarks compare main with the combined map
changes:
| workload | before | after | speedup |
|---|---:|---:|---:|
| map churn | 1.253 s | 12.5 ms | 100x |
| full OSC 8 stream | 3.576 s | 75.6 ms | 47x |
| clear and redraw | 299.1 ms | 118.3 ms | 2.5x |
Co-authored-by: Tim Culverhouse <tim@timculverhouse.com>
This commit changes a LOT of areas of the code to use decl literals
instead of redundantly referring to the type.
These changes were mostly driven by some regex searches and then manual
adjustment on a case-by-case basis.
I almost certainly missed quite a few places where decl literals could
be used, but this is a good first step in converting things, and other
instances can be addressed when they're discovered.
I tested GLFW+Metal and building the framework on macOS and tested a GTK
build on Linux, so I'm 99% sure I didn't introduce any syntax errors or
other problems with this. (fingers crossed)