diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-02-11 18:53:13 -0800 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-02-13 00:19:03 -0800 |
| commit | d12123a88cf56428874b359cb63acb8618dfbcfd (patch) | |
| tree | cb4798e72f47d303d5ac527467b021f467c86818 /lib/std/array_list.zig | |
| parent | 5b9b5e45cb710ddaad1a97813d1619755eb35a98 (diff) | |
| download | zig-d12123a88cf56428874b359cb63acb8618dfbcfd.tar.gz zig-d12123a88cf56428874b359cb63acb8618dfbcfd.zip | |
std.ArrayList: initial capacity based on cache line size
also std.MultiArrayList
Diffstat (limited to 'lib/std/array_list.zig')
| -rw-r--r-- | lib/std/array_list.zig | 38 |
1 files changed, 19 insertions, 19 deletions
diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig index 11419f975a..1b2bbcb919 100644 --- a/lib/std/array_list.zig +++ b/lib/std/array_list.zig @@ -181,7 +181,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { // a new buffer and doing our own copy. With a realloc() call, // the allocator implementation would pointlessly copy our // extra capacity. - const new_capacity = growCapacity(self.capacity, new_len); + const new_capacity = ArrayListAlignedUnmanaged(T, alignment).growCapacity(self.capacity, new_len); const old_memory = self.allocatedSlice(); if (self.allocator.remap(old_memory, new_capacity)) |new_memory| { self.items.ptr = new_memory.ptr; @@ -446,7 +446,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { if (self.capacity >= new_capacity) return; - const better_capacity = growCapacity(self.capacity, new_capacity); + const better_capacity = ArrayListAlignedUnmanaged(T, alignment).growCapacity(self.capacity, new_capacity); return self.ensureTotalCapacityPrecise(better_capacity); } @@ -1062,14 +1062,12 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ self.capacity = 0; } - /// If the current capacity is less than `new_capacity`, this function will - /// modify the array so that it can hold at least `new_capacity` items. + /// Modify the array so that it can hold at least `new_capacity` items. + /// Implements super-linear growth to achieve amortized O(1) append operations. /// Invalidates element pointers if additional memory is needed. - pub fn ensureTotalCapacity(self: *Self, allocator: Allocator, new_capacity: usize) Allocator.Error!void { + pub fn ensureTotalCapacity(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void { if (self.capacity >= new_capacity) return; - - const better_capacity = growCapacity(self.capacity, new_capacity); - return self.ensureTotalCapacityPrecise(allocator, better_capacity); + return self.ensureTotalCapacityPrecise(gpa, growCapacity(self.capacity, new_capacity)); } /// If the current capacity is less than `new_capacity`, this function will @@ -1218,18 +1216,20 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ if (self.items.len == 0) return null; return self.getLast(); } - }; -} -/// Called when memory growth is necessary. Returns a capacity larger than -/// minimum that grows super-linearly. -fn growCapacity(current: usize, minimum: usize) usize { - var new = current; - while (true) { - new +|= new / 2 + 8; - if (new >= minimum) - return new; - } + const init_capacity = @as(comptime_int, @max(1, std.atomic.cache_line / @sizeOf(T))); + + /// Called when memory growth is necessary. Returns a capacity larger than + /// minimum that grows super-linearly. + fn growCapacity(current: usize, minimum: usize) usize { + var new = current; + while (true) { + new +|= new / 2 + init_capacity; + if (new >= minimum) + return new; + } + } + }; } /// Integer addition returning `error.OutOfMemory` on overflow. |
