Improve realloc on fixed buffer allocator (#1238)
* Add test to check re-use of memory * Check if realloc has to reallocate the last allocated memory block. If so extend that block instead of allocating a new one. * Also check if the realloc actually preserves the data.
This commit is contained in:
parent
278829fc2c
commit
69e50ad2f5
46
std/heap.zig
46
std/heap.zig
@ -302,8 +302,17 @@ pub const FixedBufferAllocator = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
|
fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
|
||||||
|
const self = @fieldParentPtr(FixedBufferAllocator, "allocator", allocator);
|
||||||
|
assert(old_mem.len <= self.end_index);
|
||||||
if (new_size <= old_mem.len) {
|
if (new_size <= old_mem.len) {
|
||||||
return old_mem[0..new_size];
|
return old_mem[0..new_size];
|
||||||
|
} else if (old_mem.ptr == self.buffer.ptr + self.end_index - old_mem.len) {
|
||||||
|
const start_index = self.end_index - old_mem.len;
|
||||||
|
const new_end_index = start_index + new_size;
|
||||||
|
if (new_end_index > self.buffer.len) return error.OutOfMemory;
|
||||||
|
const result = self.buffer[start_index..new_end_index];
|
||||||
|
self.end_index = new_end_index;
|
||||||
|
return result;
|
||||||
} else {
|
} else {
|
||||||
const result = try alloc(allocator, new_size, alignment);
|
const result = try alloc(allocator, new_size, alignment);
|
||||||
mem.copy(u8, result, old_mem);
|
mem.copy(u8, result, old_mem);
|
||||||
@ -467,6 +476,35 @@ test "FixedBufferAllocator" {
|
|||||||
try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);
|
try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "FixedBufferAllocator Reuse memory on realloc" {
|
||||||
|
var small_fixed_buffer: [10]u8 = undefined;
|
||||||
|
// check if we re-use the memory
|
||||||
|
{
|
||||||
|
var fixed_buffer_allocator = FixedBufferAllocator.init(small_fixed_buffer[0..]);
|
||||||
|
|
||||||
|
var slice0 = try fixed_buffer_allocator.allocator.alloc(u8, 5);
|
||||||
|
assert(slice0.len == 5);
|
||||||
|
var slice1 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 10);
|
||||||
|
assert(slice1.ptr == slice0.ptr);
|
||||||
|
assert(slice1.len == 10);
|
||||||
|
debug.assertError(fixed_buffer_allocator.allocator.realloc(u8, slice1, 11), error.OutOfMemory);
|
||||||
|
}
|
||||||
|
// check that we don't re-use the memory if it's not the most recent block
|
||||||
|
{
|
||||||
|
var fixed_buffer_allocator = FixedBufferAllocator.init(small_fixed_buffer[0..]);
|
||||||
|
|
||||||
|
var slice0 = try fixed_buffer_allocator.allocator.alloc(u8, 2);
|
||||||
|
slice0[0] = 1;
|
||||||
|
slice0[1] = 2;
|
||||||
|
var slice1 = try fixed_buffer_allocator.allocator.alloc(u8, 2);
|
||||||
|
var slice2 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 4);
|
||||||
|
assert(slice0.ptr != slice2.ptr);
|
||||||
|
assert(slice1.ptr != slice2.ptr);
|
||||||
|
assert(slice2[0] == 1);
|
||||||
|
assert(slice2[1] == 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test "ThreadSafeFixedBufferAllocator" {
|
test "ThreadSafeFixedBufferAllocator" {
|
||||||
var fixed_buffer_allocator = ThreadSafeFixedBufferAllocator.init(test_fixed_buffer_allocator_memory[0..]);
|
var fixed_buffer_allocator = ThreadSafeFixedBufferAllocator.init(test_fixed_buffer_allocator_memory[0..]);
|
||||||
|
|
||||||
@ -482,12 +520,14 @@ fn testAllocator(allocator: *mem.Allocator) !void {
|
|||||||
item.* = try allocator.create(@intCast(i32, i));
|
item.* = try allocator.create(@intCast(i32, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (slice) |item, i| {
|
slice = try allocator.realloc(*i32, slice, 20000);
|
||||||
|
assert(slice.len == 20000);
|
||||||
|
|
||||||
|
for (slice[0..100]) |item, i| {
|
||||||
|
assert(item.* == @intCast(i32, i));
|
||||||
allocator.destroy(item);
|
allocator.destroy(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
slice = try allocator.realloc(*i32, slice, 20000);
|
|
||||||
assert(slice.len == 20000);
|
|
||||||
slice = try allocator.realloc(*i32, slice, 50);
|
slice = try allocator.realloc(*i32, slice, 50);
|
||||||
assert(slice.len == 50);
|
assert(slice.len == 50);
|
||||||
slice = try allocator.realloc(*i32, slice, 25);
|
slice = try allocator.realloc(*i32, slice, 25);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user