From 56cbbd940bfb8f49870a264c8439ed4d5b90b7c3 Mon Sep 17 00:00:00 2001 From: Qwerasd Date: Mon, 23 Dec 2024 21:41:51 -0500 Subject: [PATCH 1/2] perf(RefCountedSet): make swap metric prioritize high refcount items This experimentally yields a ~20% performance improvement as measured by running DOOM-fire-zig, which is honestly a lot more than I expected. --- src/terminal/ref_counted_set.zig | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/terminal/ref_counted_set.zig b/src/terminal/ref_counted_set.zig index ddca32482..1a58a4e5b 100644 --- a/src/terminal/ref_counted_set.zig +++ b/src/terminal/ref_counted_set.zig @@ -607,8 +607,16 @@ pub fn RefCountedSet( break; } - // This item has a lower PSL, swap it out with our held item. - if (item.meta.psl < held_item.meta.psl) { + // If this item has a lower PSL, or has equal PSL and lower ref + // count, then we swap it out with our held item. By doing this, + // items with high reference counts are prioritized for earlier + // placement. The assumption is that an item which has a higher + // reference count will be accessed more frequently, so we want + // to minimize the time it takes to find it. + if (item.meta.psl < held_item.meta.psl or + item.meta.psl == held_item.meta.psl and + item.meta.ref < held_item.meta.ref) + { // Put our held item in the bucket. table[p] = held_id; held_item.meta.bucket = p; From 3bfe4cd25ca7a5ae4d4084818b86ada9236b3bb5 Mon Sep 17 00:00:00 2001 From: Qwerasd Date: Mon, 23 Dec 2024 22:04:37 -0500 Subject: [PATCH 2/2] perf(styles): greatly improve style.hash performance By switching to one-shot hashing of the raw bytes of the struct with XxHash3 instead of using `autoHash` with Wyhash, a performance gain of around 20% can be observed in DOOM-fire-zig. --- src/terminal/style.zig | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/terminal/style.zig b/src/terminal/style.zig index 0340047e9..fe2589a46 100644 --- a/src/terminal/style.zig +++ b/src/terminal/style.zig @@ -8,8 +8,7 @@ const Offset = size.Offset; const OffsetBuf = size.OffsetBuf; const RefCountedSet = @import("ref_counted_set.zig").RefCountedSet; -const Wyhash = std.hash.Wyhash; -const autoHash = std.hash.autoHash; +const XxHash3 = std.hash.XxHash3; /// The unique identifier for a style. This is at most the number of cells /// that can fit into a terminal page. @@ -230,10 +229,13 @@ pub const Style = struct { _ = try writer.write(" }"); } + /// Hash the raw bytes of the struct with XxHash3 + /// + /// NOTE: Because the struct does not have a guaranteed in-memory layout + /// this hash is NOT suitable for serialization. If used for a hash + /// table that is then serialized, it MUST be re-hashed when read. pub fn hash(self: *const Style) u64 { - var hasher = Wyhash.init(0); - autoHash(&hasher, self.*); - return hasher.final(); + return XxHash3.hash(0, @as(*const [@sizeOf(Style)]u8, @ptrCast(self))); } test {