authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-10-23 17:01:27+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-10-25 00:21:55+01:00
log8d471cd9018d99a3a39ee94212b2d42efe755ea1
tree5bda81593e9804026360a975a3b72676b6690933
parent50752ce0f53961b300dee8dcd00ce7a96865add2
signature Commit is signed but in an unrecognized format.

Elf2: switch string table to ArrayHashMap

This seems to be a performance win, presumably thanks to the entire hash being stored which avoids redundant string comparisons.

1 files changed, 6 insertions(+), 18 deletions(-)

src/link/Elf2.zig+6-18
...@@ -4963,31 +4963,20 @@ fn stringExisting(elf: *Elf, comptime section: StringSection, key: []const u8) S...@@ -4963,31 +4963,20 @@ fn stringExisting(elf: *Elf, comptime section: StringSection, key: []const u8) S
4963}4963}
49644964
4965const StringTable = struct {4965const StringTable = struct {
4966 map: std.HashMapUnmanaged(u32, void, StringTable.Context, std.hash_map.default_max_load_percentage),4966 map: std.array_hash_map.Custom(u32, void, void, true),
4967
4968 const Context = struct {
4969 slice: []const u8,
4970
4971 pub fn eql(_: Context, lhs_key: u32, rhs_key: u32) bool {
4972 return lhs_key == rhs_key;
4973 }
4974
4975 pub fn hash(ctx: Context, key: u32) u64 {
4976 return std.hash_map.hashString(std.mem.sliceTo(ctx.slice[key..], 0));
4977 }
4978 };
49794967
4980 const Adapter = struct {4968 const Adapter = struct {
4981 slice: []const u8,4969 slice: []const u8,
49824970
4983 pub fn eql(adapter: Adapter, lhs_key: []const u8, rhs_key: u32) bool {4971 pub fn eql(adapter: Adapter, lhs_key: []const u8, rhs_key: u32, rhs_index: usize) bool {
4972 _ = rhs_index;
4984 return std.mem.startsWith(u8, adapter.slice[rhs_key..], lhs_key) and4973 return std.mem.startsWith(u8, adapter.slice[rhs_key..], lhs_key) and
4985 adapter.slice[rhs_key + lhs_key.len] == 0;4974 adapter.slice[rhs_key + lhs_key.len] == 0;
4986 }4975 }
49874976
4988 pub fn hash(_: Adapter, key: []const u8) u64 {4977 pub fn hash(_: Adapter, key: []const u8) u32 {
4989 assert(std.mem.findScalar(u8, key, 0) == null);4978 assert(std.mem.findScalar(u8, key, 0) == null);
4990 return std.hash_map.hashString(key);4979 return std.array_hash_map.hashString(key);
4991 }4980 }
4992 };4981 };
49934982
...@@ -5001,8 +4990,7 @@ const StringTable = struct {...@@ -5001,8 +4990,7 @@ const StringTable = struct {
5001 fn ensureAdditionalCapacity(st: *StringTable, elf: *Elf, shndx: Section.Index, string_len: usize) Error!void {4990 fn ensureAdditionalCapacity(st: *StringTable, elf: *Elf, shndx: Section.Index, string_len: usize) Error!void {
5002 const gpa = elf.base.comp.gpa;4991 const gpa = elf.base.comp.gpa;
5003 const ni = shndx.node(elf);4992 const ni = shndx.node(elf);
5004 const slice_const = ni.sliceConst(&elf.mf);4993 try st.map.ensureUnusedCapacity(gpa, 1);
5005 try st.map.ensureUnusedCapacityContext(gpa, 1, .{ .slice = slice_const });
5006 const size: u64 = switch (elf.shdrPtr(shndx)) {4994 const size: u64 = switch (elf.shdrPtr(shndx)) {
5007 inline else => |shdr| elf.targetLoad(&shdr.size),4995 inline else => |shdr| elf.targetLoad(&shdr.size),
5008 };4996 };