mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
std: remove loop from growCapacity
I measured this against master branch and found no statistical difference. Since this code is simpler and logically superior due to always leaving sufficient unused capacity when growing, it is preferred over status quo.
This commit is contained in:
parent
4d1b15bd9d
commit
0c1fbc4ea6
@ -2661,7 +2661,7 @@ pub const Allocating = struct {
|
|||||||
pub fn ensureTotalCapacity(a: *Allocating, new_capacity: usize) Allocator.Error!void {
|
pub fn ensureTotalCapacity(a: *Allocating, new_capacity: usize) Allocator.Error!void {
|
||||||
// Protects growing unnecessarily since better_capacity will be larger.
|
// Protects growing unnecessarily since better_capacity will be larger.
|
||||||
if (a.writer.buffer.len >= new_capacity) return;
|
if (a.writer.buffer.len >= new_capacity) return;
|
||||||
const better_capacity = ArrayList(u8).growCapacity(a.writer.buffer.len, new_capacity);
|
const better_capacity = ArrayList(u8).growCapacity(new_capacity);
|
||||||
return ensureTotalCapacityPrecise(a, better_capacity);
|
return ensureTotalCapacityPrecise(a, better_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -172,7 +172,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
|
|||||||
// a new buffer and doing our own copy. With a realloc() call,
|
// a new buffer and doing our own copy. With a realloc() call,
|
||||||
// the allocator implementation would pointlessly copy our
|
// the allocator implementation would pointlessly copy our
|
||||||
// extra capacity.
|
// extra capacity.
|
||||||
const new_capacity = Aligned(T, alignment).growCapacity(self.capacity, new_len);
|
const new_capacity = Aligned(T, alignment).growCapacity(new_len);
|
||||||
const old_memory = self.allocatedSlice();
|
const old_memory = self.allocatedSlice();
|
||||||
if (self.allocator.remap(old_memory, new_capacity)) |new_memory| {
|
if (self.allocator.remap(old_memory, new_capacity)) |new_memory| {
|
||||||
self.items.ptr = new_memory.ptr;
|
self.items.ptr = new_memory.ptr;
|
||||||
@ -408,7 +408,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type
|
|||||||
// Protects growing unnecessarily since better_capacity will be larger.
|
// Protects growing unnecessarily since better_capacity will be larger.
|
||||||
if (self.capacity >= new_capacity) return;
|
if (self.capacity >= new_capacity) return;
|
||||||
|
|
||||||
const better_capacity = Aligned(T, alignment).growCapacity(self.capacity, new_capacity);
|
const better_capacity = Aligned(T, alignment).growCapacity(new_capacity);
|
||||||
return self.ensureTotalCapacityPrecise(better_capacity);
|
return self.ensureTotalCapacityPrecise(better_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1160,7 +1160,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
|
|||||||
/// Invalidates element pointers if additional memory is needed.
|
/// Invalidates element pointers if additional memory is needed.
|
||||||
pub fn ensureTotalCapacity(self: *Self, gpa: 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;
|
if (self.capacity >= new_capacity) return;
|
||||||
return self.ensureTotalCapacityPrecise(gpa, growCapacity(self.capacity, new_capacity));
|
return self.ensureTotalCapacityPrecise(gpa, growCapacity(new_capacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the current capacity is less than `new_capacity`, this function will
|
/// If the current capacity is less than `new_capacity`, this function will
|
||||||
@ -1359,17 +1359,12 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type {
|
|||||||
return self.getLast();
|
return self.getLast();
|
||||||
}
|
}
|
||||||
|
|
||||||
const init_capacity = @as(comptime_int, @max(1, std.atomic.cache_line / @sizeOf(T)));
|
const init_capacity: comptime_int = @max(1, std.atomic.cache_line / @sizeOf(T));
|
||||||
|
|
||||||
/// Called when memory growth is necessary. Returns a capacity larger than
|
/// Called when memory growth is necessary. Returns a capacity larger than
|
||||||
/// minimum that grows super-linearly.
|
/// minimum that grows super-linearly.
|
||||||
pub fn growCapacity(current: usize, minimum: usize) usize {
|
pub fn growCapacity(minimum: usize) usize {
|
||||||
var new = current;
|
return minimum +| (minimum / 2 + init_capacity);
|
||||||
while (true) {
|
|
||||||
new +|= new / 2 + init_capacity;
|
|
||||||
if (new >= minimum)
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,7 @@ pub fn Deque(comptime T: type) type {
|
|||||||
/// Invalidates element pointers if additional memory is needed.
|
/// Invalidates element pointers if additional memory is needed.
|
||||||
pub fn ensureTotalCapacity(deque: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void {
|
pub fn ensureTotalCapacity(deque: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void {
|
||||||
if (deque.buffer.len >= new_capacity) return;
|
if (deque.buffer.len >= new_capacity) return;
|
||||||
return deque.ensureTotalCapacityPrecise(gpa, growCapacity(deque.buffer.len, new_capacity));
|
return deque.ensureTotalCapacityPrecise(gpa, std.ArrayList(T).growCapacity(new_capacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the current capacity is less than `new_capacity`, this function will
|
/// If the current capacity is less than `new_capacity`, this function will
|
||||||
@ -243,18 +243,6 @@ pub fn Deque(comptime T: type) type {
|
|||||||
return index - head_len;
|
return index - head_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const init_capacity: 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -457,24 +457,19 @@ pub fn MultiArrayList(comptime T: type) type {
|
|||||||
/// Invalidates element pointers if additional memory is needed.
|
/// Invalidates element pointers if additional memory is needed.
|
||||||
pub fn ensureTotalCapacity(self: *Self, gpa: 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;
|
if (self.capacity >= new_capacity) return;
|
||||||
return self.setCapacity(gpa, growCapacity(self.capacity, new_capacity));
|
return self.setCapacity(gpa, growCapacity(new_capacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
const init_capacity = init: {
|
const init_capacity: comptime_int = init: {
|
||||||
var max = 1;
|
var max: comptime_int = 1;
|
||||||
for (fields) |field| max = @as(comptime_int, @max(max, @sizeOf(field.type)));
|
for (fields) |field| max = @max(max, @sizeOf(field.type));
|
||||||
break :init @as(comptime_int, @max(1, std.atomic.cache_line / max));
|
break :init @max(1, std.atomic.cache_line / max);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Called when memory growth is necessary. Returns a capacity larger than
|
/// Given a lower bound of required memory capacity, returns a larger value
|
||||||
/// minimum that grows super-linearly.
|
/// with super-linear growth.
|
||||||
fn growCapacity(current: usize, minimum: usize) usize {
|
pub fn growCapacity(minimum: usize) usize {
|
||||||
var new = current;
|
return minimum +| (minimum / 2 + init_capacity);
|
||||||
while (true) {
|
|
||||||
new +|= new / 2 + init_capacity;
|
|
||||||
if (new >= minimum)
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Modify the array so that it can hold at least `additional_count` **more** items.
|
/// Modify the array so that it can hold at least `additional_count` **more** items.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user