aboutsummaryrefslogtreecommitdiff
path: root/lib/std/array_list.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-02-11 18:53:13 -0800
committerAndrew Kelley <andrew@ziglang.org>2025-02-13 00:19:03 -0800
commitd12123a88cf56428874b359cb63acb8618dfbcfd (patch)
treecb4798e72f47d303d5ac527467b021f467c86818 /lib/std/array_list.zig
parent5b9b5e45cb710ddaad1a97813d1619755eb35a98 (diff)
downloadzig-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.zig38
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.