mirror of
https://github.com/ziglang/zig.git
synced 2025-12-18 04:03:14 +00:00
std.HashMap: make ensureCapacity optimize for the expected count, add ensureCapacityExact
This commit is contained in:
parent
0afa2d040a
commit
4d42275d03
@ -135,21 +135,39 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
|
|||||||
return res.kv;
|
return res.kv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn optimizedCapacity(expected_count: usize) usize {
|
||||||
|
// ensure that the hash map will be at most 60% full if
|
||||||
|
// new_capacity items are put into the hash map
|
||||||
|
var optimized_capacity = expected_count * 5 / 3;
|
||||||
|
// round capacity to the next power of two
|
||||||
|
const is_power_of_two = optimized_capacity & (optimized_capacity-1) == 0;
|
||||||
|
if (!is_power_of_two) {
|
||||||
|
const pow = math.log2_int_ceil(usize, optimized_capacity);
|
||||||
|
optimized_capacity = math.pow(usize, 2, pow);
|
||||||
|
}
|
||||||
|
return optimized_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Increase capacity so that the hash map will be at most
|
||||||
|
/// 60% full when expected_count items are put into it
|
||||||
|
pub fn ensureCapacity(self: *Self, expected_count: usize) !void {
|
||||||
|
const optimized_capacity = optimizedCapacity(expected_count);
|
||||||
|
return self.ensureCapacityExact(optimized_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the capacity to the new capacity if the new
|
/// Sets the capacity to the new capacity if the new
|
||||||
/// capacity is greater than the current capacity.
|
/// capacity is greater than the current capacity.
|
||||||
pub fn ensureCapacity(self: *Self, new_capacity: usize) !void {
|
/// New capacity must be a power of two.
|
||||||
|
pub fn ensureCapacityExact(self: *Self, new_capacity: usize) !void {
|
||||||
|
const is_power_of_two = new_capacity & (new_capacity-1) == 0;
|
||||||
|
assert(is_power_of_two);
|
||||||
|
|
||||||
if (new_capacity <= self.entries.len) {
|
if (new_capacity <= self.entries.len) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// make sure capacity is a power of two
|
|
||||||
var capacity = new_capacity;
|
|
||||||
const is_power_of_two = capacity & (capacity-1) == 0;
|
|
||||||
if (!is_power_of_two) {
|
|
||||||
const pow = math.log2_int_ceil(usize, capacity);
|
|
||||||
capacity = math.pow(usize, 2, pow);
|
|
||||||
}
|
|
||||||
const old_entries = self.entries;
|
const old_entries = self.entries;
|
||||||
try self.initCapacity(capacity);
|
try self.initCapacity(new_capacity);
|
||||||
if (old_entries.len > 0) {
|
if (old_entries.len > 0) {
|
||||||
// dump all of the old elements into the new table
|
// dump all of the old elements into the new table
|
||||||
for (old_entries) |*old_entry| {
|
for (old_entries) |*old_entry| {
|
||||||
@ -236,11 +254,11 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
|
|||||||
|
|
||||||
fn autoCapacity(self: *Self) !void {
|
fn autoCapacity(self: *Self) !void {
|
||||||
if (self.entries.len == 0) {
|
if (self.entries.len == 0) {
|
||||||
return self.ensureCapacity(16);
|
return self.ensureCapacityExact(16);
|
||||||
}
|
}
|
||||||
// if we get too full (60%), double the capacity
|
// if we get too full (60%), double the capacity
|
||||||
if (self.size * 5 >= self.entries.len * 3) {
|
if (self.size * 5 >= self.entries.len * 3) {
|
||||||
return self.ensureCapacity(self.entries.len * 2);
|
return self.ensureCapacityExact(self.entries.len * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user