From b0cf99cf9a1eac9985c094e4f5184bc8a25e0174 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 11 Jul 2026 19:54:04 -0700 Subject: [PATCH] terminal: reduce style hash mixing cost Use the two-round SplitMix64 finalizer for the folded PackedStyle key. The previous std.hash.int u64 mixer performs three multiply rounds. Style hashing is paid for every real SGR transition, and the additional round did not improve lookup behavior for this key distribution. ReleaseFast timings are seven-run median user CPU times. | Workload | Before | After | Change | | --- | ---: | ---: | ---: | | 4,096 styles, live lookup | 0.87s | 0.83s | -4.6% | | Alternating SGR stream | 1.20s | 1.13s | -5.8% | | Truecolor SGR stream | 0.68s | 0.67s | -1.5% | | Clear/redraw SGR stream | 0.68s | 0.67s | -1.5% | --- src/terminal/style.zig | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/terminal/style.zig b/src/terminal/style.zig index 720789bb2..1d27ee0ee 100644 --- a/src/terminal/style.zig +++ b/src/terminal/style.zig @@ -530,11 +530,20 @@ pub const Style = struct { }; pub fn hash(self: *const Style) u64 { - // We pack the style in to 128 bits, fold it to 64 bits, - // then use std.hash.int to make it sufficiently uniform. + // We pack the style in to 128 bits, fold it to 64 bits, then use the + // SplitMix64 finalizer to make it sufficiently uniform: + // https://prng.di.unimi.it/splitmix64.c + // + // This finalizer provides sufficient diffusion for the folded style + // key with two multiply rounds. The u64 mixer used by std.hash.int + // has three, and benchmarks show that extra round costs throughput on + // this SGR hot path without improving style-set lookup performance. const packed_style: PackedStyle = .fromStyle(self.*); const wide: [2]u64 = @bitCast(packed_style); - return @call(.always_inline, std.hash.int, .{wide[0] ^ wide[1]}); + var result = wide[0] ^ wide[1]; + result = (result ^ (result >> 30)) *% 0xbf58476d1ce4e5b9; + result = (result ^ (result >> 27)) *% 0x94d049bb133111eb; + return result ^ (result >> 31); } comptime {