authorgravatar for sahnvour@pm.meSahnvour <sahnvour@pm.me> 2020-07-26 22:08:48+02:00
committergravatar for sahnvour@pm.meSahnvour <sahnvour@pm.me> 2020-07-26 23:04:33+02:00
logf67ce1e35fe3ecf19b50f64b9fe2d85747f7934d
treeae29d6c2a1444ed46641cb4500673bff61e6badd
parent345cb3200c353d6fb7aeb0e058986d8ca59ced1e

make use of hasUniqueRepresentation to speed up hashing facilities, fastpath in getAutoHashFn is particularly important for hashmap performance

gives a 1.18x speedup on gotta-go-fast hashmap bench

2 files changed, 14 insertions(+), 9 deletions(-)

lib/std/hash/auto_hash.zig+6-6
...@@ -56,9 +56,6 @@ pub fn hashPointer(hasher: anytype, key: anytype, comptime strat: HashStrategy)...@@ -56,9 +56,6 @@ pub fn hashPointer(hasher: anytype, key: anytype, comptime strat: HashStrategy)
56pub fn hashArray(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {56pub fn hashArray(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
57 switch (strat) {57 switch (strat) {
58 .Shallow => {58 .Shallow => {
59 // TODO detect via a trait when Key has no padding bits to
60 // hash it as an array of bytes.
61 // Otherwise, hash every element.
62 for (key) |element| {59 for (key) |element| {
63 hash(hasher, element, .Shallow);60 hash(hasher, element, .Shallow);
64 }61 }
...@@ -75,6 +72,12 @@ pub fn hashArray(hasher: anytype, key: anytype, comptime strat: HashStrategy) vo...@@ -75,6 +72,12 @@ pub fn hashArray(hasher: anytype, key: anytype, comptime strat: HashStrategy) vo
75/// Strategy is provided to determine if pointers should be followed or not.72/// Strategy is provided to determine if pointers should be followed or not.
76pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {73pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
77 const Key = @TypeOf(key);74 const Key = @TypeOf(key);
75
76 if (strat == .Shallow and comptime meta.trait.hasUniqueRepresentation(Key)) {
77 @call(.{ .modifier = .always_inline }, hasher.update, .{mem.asBytes(&key)});
78 return;
79 }
80
78 switch (@typeInfo(Key)) {81 switch (@typeInfo(Key)) {
79 .NoReturn,82 .NoReturn,
80 .Opaque,83 .Opaque,
...@@ -119,9 +122,6 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {...@@ -119,9 +122,6 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
119 },122 },
120123
121 .Struct => |info| {124 .Struct => |info| {
122 // TODO detect via a trait when Key has no padding bits to
123 // hash it as an array of bytes.
124 // Otherwise, hash every field.
125 inline for (info.fields) |field| {125 inline for (info.fields) |field| {
126 // We reuse the hash of the previous field as the seed for the126 // We reuse the hash of the previous field as the seed for the
127 // next one so that they're dependant.127 // next one so that they're dependant.
lib/std/hash_map.zig+8-3
...@@ -5,6 +5,7 @@ const testing = std.testing;...@@ -5,6 +5,7 @@ const testing = std.testing;
5const math = std.math;5const math = std.math;
6const mem = std.mem;6const mem = std.mem;
7const meta = std.meta;7const meta = std.meta;
8const trait = meta.trait;
8const autoHash = std.hash.autoHash;9const autoHash = std.hash.autoHash;
9const Wyhash = std.hash.Wyhash;10const Wyhash = std.hash.Wyhash;
10const Allocator = mem.Allocator;11const Allocator = mem.Allocator;
...@@ -1023,9 +1024,13 @@ pub fn getTrivialEqlFn(comptime K: type) (fn (K, K) bool) {...@@ -1023,9 +1024,13 @@ pub fn getTrivialEqlFn(comptime K: type) (fn (K, K) bool) {
1023pub fn getAutoHashFn(comptime K: type) (fn (K) u32) {1024pub fn getAutoHashFn(comptime K: type) (fn (K) u32) {
1024 return struct {1025 return struct {
1025 fn hash(key: K) u32 {1026 fn hash(key: K) u32 {
1026 var hasher = Wyhash.init(0);1027 if (comptime trait.hasUniqueRepresentation(K)) {
1027 autoHash(&hasher, key);1028 return @truncate(u32, Wyhash.hash(0, std.mem.asBytes(&key)));
1028 return @truncate(u32, hasher.final());1029 } else {
1030 var hasher = Wyhash.init(0);
1031 autoHash(&hasher, key);
1032 return @truncate(u32, hasher.final());
1033 }
1029 }1034 }
1030 }.hash;1035 }.hash;
1031}1036}