authorgravatar for BarabasGitHub@users.noreply.github.comBas van den Berg <BarabasGitHub@users.noreply.github.com> 2018-07-14 22:31:11+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-14 16:31:11-04:00
log69e50ad2f54bc446b2258f464f9b09e78e132d45
treef9861f568089370da238564cc54924bb2643fcd4
parent278829fc2cc23e55b09915ce07ce1ec2dbf7e68b

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.

1 files changed, 43 insertions(+), 3 deletions(-)

std/heap.zig+43-3
...@@ -302,8 +302,17 @@ pub const FixedBufferAllocator = struct {...@@ -302,8 +302,17 @@ pub const FixedBufferAllocator = struct {
302 }302 }
303303
304 fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {304 fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
305 const self = @fieldParentPtr(FixedBufferAllocator, "allocator", allocator);
306 assert(old_mem.len <= self.end_index);
305 if (new_size <= old_mem.len) {307 if (new_size <= old_mem.len) {
306 return old_mem[0..new_size];308 return old_mem[0..new_size];
309 } else if (old_mem.ptr == self.buffer.ptr + self.end_index - old_mem.len) {
310 const start_index = self.end_index - old_mem.len;
311 const new_end_index = start_index + new_size;
312 if (new_end_index > self.buffer.len) return error.OutOfMemory;
313 const result = self.buffer[start_index..new_end_index];
314 self.end_index = new_end_index;
315 return result;
307 } else {316 } else {
308 const result = try alloc(allocator, new_size, alignment);317 const result = try alloc(allocator, new_size, alignment);
309 mem.copy(u8, result, old_mem);318 mem.copy(u8, result, old_mem);
...@@ -467,6 +476,35 @@ test "FixedBufferAllocator" {...@@ -467,6 +476,35 @@ test "FixedBufferAllocator" {
467 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);476 try testAllocatorLargeAlignment(&fixed_buffer_allocator.allocator);
468}477}
469478
479test "FixedBufferAllocator Reuse memory on realloc" {
480 var small_fixed_buffer: [10]u8 = undefined;
481 // check if we re-use the memory
482 {
483 var fixed_buffer_allocator = FixedBufferAllocator.init(small_fixed_buffer[0..]);
484
485 var slice0 = try fixed_buffer_allocator.allocator.alloc(u8, 5);
486 assert(slice0.len == 5);
487 var slice1 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 10);
488 assert(slice1.ptr == slice0.ptr);
489 assert(slice1.len == 10);
490 debug.assertError(fixed_buffer_allocator.allocator.realloc(u8, slice1, 11), error.OutOfMemory);
491 }
492 // check that we don't re-use the memory if it's not the most recent block
493 {
494 var fixed_buffer_allocator = FixedBufferAllocator.init(small_fixed_buffer[0..]);
495
496 var slice0 = try fixed_buffer_allocator.allocator.alloc(u8, 2);
497 slice0[0] = 1;
498 slice0[1] = 2;
499 var slice1 = try fixed_buffer_allocator.allocator.alloc(u8, 2);
500 var slice2 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 4);
501 assert(slice0.ptr != slice2.ptr);
502 assert(slice1.ptr != slice2.ptr);
503 assert(slice2[0] == 1);
504 assert(slice2[1] == 2);
505 }
506}
507
470test "ThreadSafeFixedBufferAllocator" {508test "ThreadSafeFixedBufferAllocator" {
471 var fixed_buffer_allocator = ThreadSafeFixedBufferAllocator.init(test_fixed_buffer_allocator_memory[0..]);509 var fixed_buffer_allocator = ThreadSafeFixedBufferAllocator.init(test_fixed_buffer_allocator_memory[0..]);
472510
...@@ -482,12 +520,14 @@ fn testAllocator(allocator: *mem.Allocator) !void {...@@ -482,12 +520,14 @@ fn testAllocator(allocator: *mem.Allocator) !void {
482 item.* = try allocator.create(@intCast(i32, i));520 item.* = try allocator.create(@intCast(i32, i));
483 }521 }
484522
485 for (slice) |item, i| {523 slice = try allocator.realloc(*i32, slice, 20000);
524 assert(slice.len == 20000);
525
526 for (slice[0..100]) |item, i| {
527 assert(item.* == @intCast(i32, i));
486 allocator.destroy(item);528 allocator.destroy(item);
487 }529 }
488530
489 slice = try allocator.realloc(*i32, slice, 20000);
490 assert(slice.len == 20000);
491 slice = try allocator.realloc(*i32, slice, 50);531 slice = try allocator.realloc(*i32, slice, 50);
492 assert(slice.len == 50);532 assert(slice.len == 50);
493 slice = try allocator.realloc(*i32, slice, 25);533 slice = try allocator.realloc(*i32, slice, 25);