fn bucketForAddress(address: usize) *Bucket address: usize17589
17590
17591
17592
17593
17594
17595
17596
17597
17598
17599
17600
17601
17602
17603
17604
17605
17606
17607
17608
17609
17610
17611 fn bucketForAddress(address: usize) *Bucket {
const global = struct {
/// Length must be a power of two. The longer this array, the less likely contention is
/// between different futexes. This length seems like it'll provide a reasonable balance
/// between contention and memory usage: assuming a 128-byte `Bucket` (due to cache line
/// alignment), this uses 32 KiB of memory.
var buckets: [256]Bucket = @splat(.init);
};
// Here we use Fibonacci hashing: the golden ratio can be used to evenly redistribute input
// values across a range, giving a poor, but extremely quick to compute, hash.
// This literal is the rounded value of '2^64 / phi' (where 'phi' is the golden ratio). The
// shift then converts it to '2^b / phi', where 'b' is the pointer bit width.
const fibonacci_multiplier = 0x9E3779B97F4A7C15 >> (64 - @bitSizeOf(usize));
const hashed = address *% fibonacci_multiplier;
comptime assert(std.math.isPowerOfTwo(global.buckets.len));
// The high bits of `hashed` have better entropy than the low bits.
const index = hashed >> (@bitSizeOf(usize) - @ctz(global.buckets.len));
return &global.buckets[index];
}