mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
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
This commit is contained in:
parent
345cb3200c
commit
f67ce1e35f
@ -56,9 +56,6 @@ pub fn hashPointer(hasher: anytype, key: anytype, comptime strat: HashStrategy)
|
|||||||
pub fn hashArray(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
|
pub fn hashArray(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
|
||||||
switch (strat) {
|
switch (strat) {
|
||||||
.Shallow => {
|
.Shallow => {
|
||||||
// TODO detect via a trait when Key has no padding bits to
|
|
||||||
// hash it as an array of bytes.
|
|
||||||
// Otherwise, hash every element.
|
|
||||||
for (key) |element| {
|
for (key) |element| {
|
||||||
hash(hasher, element, .Shallow);
|
hash(hasher, element, .Shallow);
|
||||||
}
|
}
|
||||||
@ -75,6 +72,12 @@ pub fn hashArray(hasher: anytype, key: anytype, comptime strat: HashStrategy) vo
|
|||||||
/// Strategy is provided to determine if pointers should be followed or not.
|
/// Strategy is provided to determine if pointers should be followed or not.
|
||||||
pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
|
pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
|
||||||
const Key = @TypeOf(key);
|
const Key = @TypeOf(key);
|
||||||
|
|
||||||
|
if (strat == .Shallow and comptime meta.trait.hasUniqueRepresentation(Key)) {
|
||||||
|
@call(.{ .modifier = .always_inline }, hasher.update, .{mem.asBytes(&key)});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (@typeInfo(Key)) {
|
switch (@typeInfo(Key)) {
|
||||||
.NoReturn,
|
.NoReturn,
|
||||||
.Opaque,
|
.Opaque,
|
||||||
@ -119,9 +122,6 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
|
|||||||
},
|
},
|
||||||
|
|
||||||
.Struct => |info| {
|
.Struct => |info| {
|
||||||
// TODO detect via a trait when Key has no padding bits to
|
|
||||||
// hash it as an array of bytes.
|
|
||||||
// Otherwise, hash every field.
|
|
||||||
inline for (info.fields) |field| {
|
inline for (info.fields) |field| {
|
||||||
// We reuse the hash of the previous field as the seed for the
|
// We reuse the hash of the previous field as the seed for the
|
||||||
// next one so that they're dependant.
|
// next one so that they're dependant.
|
||||||
|
|||||||
@ -5,6 +5,7 @@ const testing = std.testing;
|
|||||||
const math = std.math;
|
const math = std.math;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const meta = std.meta;
|
const meta = std.meta;
|
||||||
|
const trait = meta.trait;
|
||||||
const autoHash = std.hash.autoHash;
|
const autoHash = std.hash.autoHash;
|
||||||
const Wyhash = std.hash.Wyhash;
|
const Wyhash = std.hash.Wyhash;
|
||||||
const Allocator = mem.Allocator;
|
const Allocator = mem.Allocator;
|
||||||
@ -1023,9 +1024,13 @@ pub fn getTrivialEqlFn(comptime K: type) (fn (K, K) bool) {
|
|||||||
pub fn getAutoHashFn(comptime K: type) (fn (K) u32) {
|
pub fn getAutoHashFn(comptime K: type) (fn (K) u32) {
|
||||||
return struct {
|
return struct {
|
||||||
fn hash(key: K) u32 {
|
fn hash(key: K) u32 {
|
||||||
var hasher = Wyhash.init(0);
|
if (comptime trait.hasUniqueRepresentation(K)) {
|
||||||
autoHash(&hasher, key);
|
return @truncate(u32, Wyhash.hash(0, std.mem.asBytes(&key)));
|
||||||
return @truncate(u32, hasher.final());
|
} else {
|
||||||
|
var hasher = Wyhash.init(0);
|
||||||
|
autoHash(&hasher, key);
|
||||||
|
return @truncate(u32, hasher.final());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.hash;
|
}.hash;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user