render: hash the glyph cache keys with foldhash #397

Merged
natsukium merged 1 commit from render/glyph-foldhash into main 2026-09-25 09:02:50 +09:00
Owner

The client's glyph cache hashed its per-cell keys with std's SipHash. On every frame the renderer walks each cell and looks it up in the primed set and the slots map. A DOOM-fire profile put that hashing at about 14% of the client main thread's samples.

Both containers now use foldhash::fast::RandomState. The keys come from PTY output: the grid's chars and OSC 66 sizing. The seed is therefore random per process, not the FixedState that felis-grid's intern tables use. Those tables tolerate a fixed seed because the style sweep bounds them. slots is not bounded: a glyph that rasterizes blank is cached without using atlas space, so it never triggers the reset that clears the map. With a fixed seed, a producer could precompute keys that share a bucket. The blank ones among them would pile up until something else fills the atlas and resets it. The random seed measured no slower than FixedState, so nothing is traded for it. The unbounded growth itself is #406.

Measured on an M4 Max: release build, default config, three alternating runs against main, 10 s of DOOM-fire each.

main this PR
client CPU time 7.86-8.04 s 7.29-7.44 s
frame rate 2,408-2,422 fps 2,409-2,443 fps
daemon CPU time 17.63-17.89 s 18.15-18.29 s

The daemon code is identical in both builds, yet its CPU time was about 2% higher in every run with this PR. The cause is unverified. One possibility is that a cheaper client answers more of the daemon's frames; the frame rate did not change.

cargo nextest run -p felis-render-wgpu: 267/267 pass. cargo clippy -p felis-render-wgpu --all-targets -D warnings: clean.

The client's glyph cache hashed its per-cell keys with std's SipHash. On every frame the renderer walks each cell and looks it up in the `primed` set and the `slots` map. A DOOM-fire profile put that hashing at about 14% of the client main thread's samples. Both containers now use `foldhash::fast::RandomState`. The keys come from PTY output: the grid's chars and OSC 66 sizing. The seed is therefore random per process, not the `FixedState` that felis-grid's intern tables use. Those tables tolerate a fixed seed because the style sweep bounds them. `slots` is not bounded: a glyph that rasterizes blank is cached without using atlas space, so it never triggers the reset that clears the map. With a fixed seed, a producer could precompute keys that share a bucket. The blank ones among them would pile up until something else fills the atlas and resets it. The random seed measured no slower than `FixedState`, so nothing is traded for it. The unbounded growth itself is #406. Measured on an M4 Max: release build, default config, three alternating runs against main, 10 s of DOOM-fire each. | | main | this PR | |---|---|---| | client CPU time | 7.86-8.04 s | 7.29-7.44 s | | frame rate | 2,408-2,422 fps | 2,409-2,443 fps | | daemon CPU time | 17.63-17.89 s | 18.15-18.29 s | The daemon code is identical in both builds, yet its CPU time was about 2% higher in every run with this PR. The cause is unverified. One possibility is that a cheaper client answers more of the daemon's frames; the frame rate did not change. `cargo nextest run -p felis-render-wgpu`: 267/267 pass. `cargo clippy -p felis-render-wgpu --all-targets -D warnings`: clean.
render: hash the glyph cache keys with foldhash
Some checks failed
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m4s
pr / wire schema is compatible with the base (pull_request) Successful in 17s
pr / frontend smoke (x86_64-linux) (pull_request) Has been cancelled
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
bench / Criterion regression gate (pull_request) Successful in 2m12s
darwin / detect relevant changes (pull_request) Successful in 4s
darwin / darwin docs-only no-op (pull_request) Has been skipped
pr / nix flake check (pull_request) Successful in 1m6s
darwin / build felis (aarch64-darwin) (pull_request) Successful in 2m12s
darwin / publish felis (aarch64-darwin) (pull_request) Has been skipped
pr / cargo build / clippy / test / deny (pull_request) Successful in 1m34s
pr / publish felis (x86_64-linux) (pull_request) Has been cancelled
windows / detect relevant changes (pull_request) Has been cancelled
windows / cargo clippy (Windows cross) (pull_request) Has been cancelled
windows / cargo nextest (Windows) (pull_request) Has been cancelled
windows / frontend smoke (Windows) (pull_request) Has been cancelled
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
windows / windows docs-only no-op (pull_request) Has been cancelled
9f9f9d5c9c
The client walks every cell of the grid on every frame, and each cell
costs two lookups keyed on small integer tuples: the `primed` set that
deduplicates the walk and the `slots` map that resolves the atlas
slot. Both used std's SipHash, which a samply profile of DOOM-fire put
at about 14% of the client main thread's samples. The keys come from
the font stack and the grid, not from anything a peer can choose to
collide, so the DoS resistance SipHash buys is not needed here; felis
grid's intern tables already use foldhash for the same reason.

Measured on an M4 Max (release, default config, three alternating runs
against main, 10 s of DOOM-fire each):
- client CPU time: 7.89-8.07 -> 6.70-6.87 s
- frame rate: 2,403-2,419 -> 2,395-2,422 fps (unchanged)
- daemon CPU time: unchanged

Assisted-by: Claude Code:Opus 5.5
natsukium force-pushed render/glyph-foldhash from 9f9f9d5c9c
Some checks failed
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m4s
pr / wire schema is compatible with the base (pull_request) Successful in 17s
pr / frontend smoke (x86_64-linux) (pull_request) Has been cancelled
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
bench / Criterion regression gate (pull_request) Successful in 2m12s
darwin / detect relevant changes (pull_request) Successful in 4s
darwin / darwin docs-only no-op (pull_request) Has been skipped
pr / nix flake check (pull_request) Successful in 1m6s
darwin / build felis (aarch64-darwin) (pull_request) Successful in 2m12s
darwin / publish felis (aarch64-darwin) (pull_request) Has been skipped
pr / cargo build / clippy / test / deny (pull_request) Successful in 1m34s
pr / publish felis (x86_64-linux) (pull_request) Has been cancelled
windows / detect relevant changes (pull_request) Has been cancelled
windows / cargo clippy (Windows cross) (pull_request) Has been cancelled
windows / cargo nextest (Windows) (pull_request) Has been cancelled
windows / frontend smoke (Windows) (pull_request) Has been cancelled
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
windows / windows docs-only no-op (pull_request) Has been cancelled
to c9762f90be
Some checks failed
fuzz / cargo fuzz smoke (per target) (pull_request) Has been cancelled
pr / nix flake check (pull_request) Has been cancelled
pr / cargo build / clippy / test / deny (pull_request) Has been cancelled
pr / wire schema is compatible with the base (pull_request) Has been cancelled
pr / frontend smoke (x86_64-linux) (pull_request) Has been cancelled
pr / publish felis (x86_64-linux) (pull_request) Has been cancelled
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Has been cancelled
darwin / build felis (aarch64-darwin) (pull_request) Has been cancelled
darwin / publish felis (aarch64-darwin) (pull_request) Has been cancelled
darwin / darwin docs-only no-op (pull_request) Has been cancelled
bench / Criterion regression gate (pull_request) Has been cancelled
windows / detect relevant changes (pull_request) Has been cancelled
windows / cargo clippy (Windows cross) (pull_request) Has been cancelled
windows / cargo nextest (Windows) (pull_request) Has been cancelled
windows / frontend smoke (Windows) (pull_request) Has been cancelled
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
windows / windows docs-only no-op (pull_request) Has been cancelled
2026-09-25 01:36:30 +09:00
Compare
natsukium force-pushed render/glyph-foldhash from c9762f90be
Some checks failed
fuzz / cargo fuzz smoke (per target) (pull_request) Has been cancelled
pr / nix flake check (pull_request) Has been cancelled
pr / cargo build / clippy / test / deny (pull_request) Has been cancelled
pr / wire schema is compatible with the base (pull_request) Has been cancelled
pr / frontend smoke (x86_64-linux) (pull_request) Has been cancelled
pr / publish felis (x86_64-linux) (pull_request) Has been cancelled
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Has been cancelled
darwin / build felis (aarch64-darwin) (pull_request) Has been cancelled
darwin / publish felis (aarch64-darwin) (pull_request) Has been cancelled
darwin / darwin docs-only no-op (pull_request) Has been cancelled
bench / Criterion regression gate (pull_request) Has been cancelled
windows / detect relevant changes (pull_request) Has been cancelled
windows / cargo clippy (Windows cross) (pull_request) Has been cancelled
windows / cargo nextest (Windows) (pull_request) Has been cancelled
windows / frontend smoke (Windows) (pull_request) Has been cancelled
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
windows / windows docs-only no-op (pull_request) Has been cancelled
to 1f9eb8cf79
All checks were successful
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
bench / Criterion full-suite snapshot (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 53s
darwin / publish felis (aarch64-darwin) (pull_request) Has been skipped
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m4s
pr / cargo build / clippy / test / deny (pull_request) Successful in 1m34s
windows / cargo nextest (Windows) (pull_request) Successful in 4m18s
windows / frontend smoke (Windows) (pull_request) Successful in 1m30s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
bench / Criterion regression gate (pull_request) Successful in 2m12s
darwin / detect relevant changes (pull_request) Successful in 4s
darwin / darwin docs-only no-op (pull_request) Has been skipped
pr / nix flake check (pull_request) Successful in 32s
pr / wire schema is compatible with the base (pull_request) Successful in 14s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 1m21s
pr / publish felis (x86_64-linux) (pull_request) Has been skipped
windows / detect relevant changes (pull_request) Successful in 5s
windows / windows docs-only no-op (pull_request) Has been skipped
windows / cargo clippy (Windows cross) (pull_request) Successful in 22s
2026-09-25 01:36:46 +09:00
Compare
natsukium force-pushed render/glyph-foldhash from 1f9eb8cf79
All checks were successful
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
bench / Criterion full-suite snapshot (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 53s
darwin / publish felis (aarch64-darwin) (pull_request) Has been skipped
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m4s
pr / cargo build / clippy / test / deny (pull_request) Successful in 1m34s
windows / cargo nextest (Windows) (pull_request) Successful in 4m18s
windows / frontend smoke (Windows) (pull_request) Successful in 1m30s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
bench / Criterion regression gate (pull_request) Successful in 2m12s
darwin / detect relevant changes (pull_request) Successful in 4s
darwin / darwin docs-only no-op (pull_request) Has been skipped
pr / nix flake check (pull_request) Successful in 32s
pr / wire schema is compatible with the base (pull_request) Successful in 14s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 1m21s
pr / publish felis (x86_64-linux) (pull_request) Has been skipped
windows / detect relevant changes (pull_request) Successful in 5s
windows / windows docs-only no-op (pull_request) Has been skipped
windows / cargo clippy (Windows cross) (pull_request) Successful in 22s
to 63ccb930c7
Some checks failed
bench / Criterion regression gate (pull_request) Has been cancelled
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Has been cancelled
darwin / build felis (aarch64-darwin) (pull_request) Has been cancelled
darwin / publish felis (aarch64-darwin) (pull_request) Has been cancelled
darwin / darwin docs-only no-op (pull_request) Has been cancelled
fuzz / cargo fuzz smoke (per target) (pull_request) Has been cancelled
pr / nix flake check (pull_request) Has been cancelled
pr / cargo build / clippy / test / deny (pull_request) Has been cancelled
pr / wire schema is compatible with the base (pull_request) Has been cancelled
pr / frontend smoke (x86_64-linux) (pull_request) Has been cancelled
pr / publish felis (x86_64-linux) (pull_request) Has been cancelled
windows / detect relevant changes (pull_request) Has been cancelled
windows / cargo clippy (Windows cross) (pull_request) Has been cancelled
windows / cargo nextest (Windows) (pull_request) Has been cancelled
windows / frontend smoke (Windows) (pull_request) Has been cancelled
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
windows / windows docs-only no-op (pull_request) Has been cancelled
2026-09-25 02:07:13 +09:00
Compare
natsukium force-pushed render/glyph-foldhash from 63ccb930c7
Some checks failed
bench / Criterion regression gate (pull_request) Has been cancelled
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Has been cancelled
darwin / build felis (aarch64-darwin) (pull_request) Has been cancelled
darwin / publish felis (aarch64-darwin) (pull_request) Has been cancelled
darwin / darwin docs-only no-op (pull_request) Has been cancelled
fuzz / cargo fuzz smoke (per target) (pull_request) Has been cancelled
pr / nix flake check (pull_request) Has been cancelled
pr / cargo build / clippy / test / deny (pull_request) Has been cancelled
pr / wire schema is compatible with the base (pull_request) Has been cancelled
pr / frontend smoke (x86_64-linux) (pull_request) Has been cancelled
pr / publish felis (x86_64-linux) (pull_request) Has been cancelled
windows / detect relevant changes (pull_request) Has been cancelled
windows / cargo clippy (Windows cross) (pull_request) Has been cancelled
windows / cargo nextest (Windows) (pull_request) Has been cancelled
windows / frontend smoke (Windows) (pull_request) Has been cancelled
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
windows / windows docs-only no-op (pull_request) Has been cancelled
to 450344a59f
Some checks failed
bench / Criterion regression gate (pull_request) Failing after 2m7s
darwin / detect relevant changes (pull_request) Successful in 4s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 58s
darwin / publish felis (aarch64-darwin) (pull_request) Has been skipped
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m8s
pr / cargo build / clippy / test / deny (pull_request) Successful in 1m47s
pr / wire schema is compatible with the base (pull_request) Successful in 13s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 1m28s
windows / cargo clippy (Windows cross) (pull_request) Successful in 13s
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
pr / nix flake check (pull_request) Successful in 38s
pr / publish felis (x86_64-linux) (pull_request) Has been skipped
windows / detect relevant changes (pull_request) Successful in 4s
windows / windows docs-only no-op (pull_request) Has been skipped
windows / cargo nextest (Windows) (pull_request) Successful in 22m2s
windows / frontend smoke (Windows) (pull_request) Successful in 4m38s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
2026-09-25 02:08:41 +09:00
Compare
natsukium force-pushed render/glyph-foldhash from 450344a59f
Some checks failed
bench / Criterion regression gate (pull_request) Failing after 2m7s
darwin / detect relevant changes (pull_request) Successful in 4s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 58s
darwin / publish felis (aarch64-darwin) (pull_request) Has been skipped
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m8s
pr / cargo build / clippy / test / deny (pull_request) Successful in 1m47s
pr / wire schema is compatible with the base (pull_request) Successful in 13s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 1m28s
windows / cargo clippy (Windows cross) (pull_request) Successful in 13s
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
pr / nix flake check (pull_request) Successful in 38s
pr / publish felis (x86_64-linux) (pull_request) Has been skipped
windows / detect relevant changes (pull_request) Successful in 4s
windows / windows docs-only no-op (pull_request) Has been skipped
windows / cargo nextest (Windows) (pull_request) Successful in 22m2s
windows / frontend smoke (Windows) (pull_request) Successful in 4m38s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
to 990c95947f
Some checks failed
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
pr / nix flake check (pull_request) Has been cancelled
pr / cargo build / clippy / test / deny (pull_request) Has been cancelled
pr / wire schema is compatible with the base (pull_request) Has been cancelled
pr / frontend smoke (x86_64-linux) (pull_request) Has been cancelled
pr / publish felis (x86_64-linux) (pull_request) Has been cancelled
windows / detect relevant changes (pull_request) Has been cancelled
windows / cargo clippy (Windows cross) (pull_request) Has been cancelled
windows / cargo nextest (Windows) (pull_request) Has been cancelled
windows / frontend smoke (Windows) (pull_request) Has been cancelled
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
windows / windows docs-only no-op (pull_request) Has been cancelled
darwin / detect relevant changes (pull_request) Has been cancelled
darwin / build felis (aarch64-darwin) (pull_request) Has been cancelled
darwin / publish felis (aarch64-darwin) (pull_request) Has been cancelled
darwin / darwin docs-only no-op (pull_request) Has been cancelled
bench / Criterion regression gate (pull_request) Successful in 2m18s
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m6s
2026-09-25 09:01:41 +09:00
Compare
natsukium deleted branch render/glyph-foldhash 2026-09-25 09:02:50 +09:00
Commenting is not possible because the repository is archived.
No description provided.