authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-08 16:20:51-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-08 16:20:51-08:00
logb09e3efad444a0008f8a6cd858f9b4c45f23f743
treeff628049f75ce8e52855cd299281b81aad3af1fd
parentbb5a4036e82ef15ac73003124fbf1adf3455e6d7

std.heap.SmpAllocator: alternate freelist accounting

Freelist length accounting in alloc had a negative impact, especially with the integer type bumped up to u16, so I changed the system to be based on counting slabs rather than total allocations.

1 files changed, 5 insertions(+), 6 deletions(-)

lib/std/heap/SmpAllocator.zig+5-6
...@@ -51,9 +51,9 @@ const slab_len: usize = @max(std.heap.page_size_max, 64 * 1024);...@@ -51,9 +51,9 @@ const slab_len: usize = @max(std.heap.page_size_max, 64 * 1024);
51/// Because of storing free list pointers, the minimum size class is 3.51/// Because of storing free list pointers, the minimum size class is 3.
52const min_class = math.log2(@sizeOf(usize));52const min_class = math.log2(@sizeOf(usize));
53const size_class_count = math.log2(slab_len) - min_class;53const size_class_count = math.log2(slab_len) - min_class;
54/// When a freelist length exceeds this number, a `free` will rotate up to54/// When a freelist length exceeds this number of slabs, a `free` will rotate
55/// `max_free_search` times before pushing.55/// up to `max_free_search` times before pushing.
56const max_freelist_len: u8 = 255;56const max_freelist_len = 255;
57const max_free_search = 1;57const max_free_search = 1;
58/// Before mapping a fresh page, `alloc` will rotate this many times.58/// Before mapping a fresh page, `alloc` will rotate this many times.
59const max_alloc_search = 1;59const max_alloc_search = 1;
...@@ -142,7 +142,6 @@ fn alloc(context: *anyopaque, len: usize, alignment: mem.Alignment, ra: usize) ?...@@ -142,7 +142,6 @@ fn alloc(context: *anyopaque, len: usize, alignment: mem.Alignment, ra: usize) ?
142 defer t.unlock();142 defer t.unlock();
143 const node: *usize = @ptrFromInt(top_free_ptr);143 const node: *usize = @ptrFromInt(top_free_ptr);
144 t.frees[class] = node.*;144 t.frees[class] = node.*;
145 t.freelist_lens[class] -|= 1;
146 return @ptrFromInt(top_free_ptr);145 return @ptrFromInt(top_free_ptr);
147 }146 }
148147
...@@ -223,7 +222,7 @@ fn free(context: *anyopaque, memory: []u8, alignment: mem.Alignment, ra: usize)...@@ -223,7 +222,7 @@ fn free(context: *anyopaque, memory: []u8, alignment: mem.Alignment, ra: usize)
223 if (freelist_len < max_freelist_len) {222 if (freelist_len < max_freelist_len) {
224 @branchHint(.likely);223 @branchHint(.likely);
225 defer t.unlock();224 defer t.unlock();
226 t.freelist_lens[class] = freelist_len +| 1;225 t.freelist_lens[class] = freelist_len +| @intFromBool((@intFromPtr(node) % slab_len) == 0);
227 node.* = t.frees[class];226 node.* = t.frees[class];
228 t.frees[class] = @intFromPtr(node);227 t.frees[class] = @intFromPtr(node);
229 return;228 return;
...@@ -231,7 +230,7 @@ fn free(context: *anyopaque, memory: []u8, alignment: mem.Alignment, ra: usize)...@@ -231,7 +230,7 @@ fn free(context: *anyopaque, memory: []u8, alignment: mem.Alignment, ra: usize)
231230
232 if (search_count >= max_free_search) {231 if (search_count >= max_free_search) {
233 defer t.unlock();232 defer t.unlock();
234 t.freelist_lens[class] = freelist_len +| 1;233 t.freelist_lens[class] = freelist_len +| @intFromBool((@intFromPtr(node) % slab_len) == 0);
235 node.* = t.frees[class];234 node.* = t.frees[class];
236 t.frees[class] = @intFromPtr(node);235 t.frees[class] = @intFromPtr(node);
237 return;236 return;