BuildChunk accumulated packed multi-Z strata into a List<byte>, which grew by
doubling (256 -> 512 -> 1024 -> ...) and then paid a final ToArray(). A full map
bake runs this ~114k times. It now writes into a byte[] rented from
STArrayPool<byte>.Shared via a WriteStratum span writer, and hands the chunk a
single exact-size copy.
This required tightening the record-fit guard. It reserved headroom for 8 strata
(StratumByteLength * 8) while ComputeStandableSurfaceZs can return up to 16, so a
cell could write 305 bytes past a 65,383-byte offset. Against a List that was
benign - it just grew past 64KB, and offsets stayed under the NoStrata sentinel.
Against a fixed-size rented buffer it is an out-of-bounds write. The guard is now
exact (strataLen + recordLength <= NoStrata), which also proves no emitted offset
can collide with the NoStrata == ushort.MaxValue sentinel.
Also:
- ShouldPromoteAfterMiss did two dictionary lookups per miss (TryGetValue, then an
indexer assignment that re-hashes and re-probes). It now mutates the entry in
place through CollectionsMarshal.GetValueRefOrNullRef. This runs on every
uncached chunk touch during A* expansion, so it is the one change here that
lands on the query path. The window-expiry branch keeps its explicit early
return so threshold=1 still resets rather than promoting.
- Drop StepProbe.ComputeStrataAt and ComputedStratum. Dead code, and the last
per-call array allocation in the probe.
- Collapse six 18-argument `new StepMask(0, 0, ..., kind)` blocks into
Fallthrough(kind), and the thrice-repeated telemetry switch into
RecordServed(kind). No behavior change; TryGetMask goes from ~220 to ~90 lines.
TryGetMask itself was already allocation-free (StepMask is a readonly struct,
StaticTileEnumerable is a ref struct, ChunkMissState is a struct), so this is a
bake-throughput and GC-churn win rather than a query-latency one.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>