The remap function in Zig's memory allocator interface is supposed to "attempt to expand or shrink memory, allowing relocation". In particular, it mentions that...
A
null
return value indicates that the resize would be equivalent to allocating new memory, copying the bytes from the old memory, and then freeing the old memory. In such case, it is more efficient for the caller to perform the copy.
I don't understand the claim that it is more efficient to perform a copy. If I want to copy some block of memory, I will have to allocate some new memory, copy the bytes over and (eventually) free the old block anyways. So what efficiency am I gaining?
The only thing I can think of is if I already have an already allocated block of memory that I can reuse for copying in which case I avoid the allocation step.
The remap function in Zig's memory allocator interface is supposed to "attempt to expand or shrink memory, allowing relocation". In particular, it mentions that...
A
null
return value indicates that the resize would be equivalent to allocating new memory, copying the bytes from the old memory, and then freeing the old memory. In such case, it is more efficient for the caller to perform the copy.
I don't understand the claim that it is more efficient to perform a copy. If I want to copy some block of memory, I will have to allocate some new memory, copy the bytes over and (eventually) free the old block anyways. So what efficiency am I gaining?
The only thing I can think of is if I already have an already allocated block of memory that I can reuse for copying in which case I avoid the allocation step.
Share Improve this question asked 2 days ago wildcatwildcat 711 silver badge4 bronze badges 1 |1 Answer
Reset to default 1remap
is not in any actual Zig release yet. It was checked into the master branch 2 days ago. It may not actually make it into any actual release.
That said, looking at the uses of remap
that were introduced in the same commit, we can see the kinds of cases that motivated this interface. The idea is that the caller can't perform the alloc/copy/free sequence more efficiently than remap
, but it might not want to do that specific alloc/copy/free sequence anyway.
For example, in array_list.zig
, under addManyAt
:
const new_capacity = 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;
self.capacity = new_memory.len;
return addManyAtAssumeCapacity(self, index, count);
}
// Make a new allocation, avoiding `ensureTotalCapacity` in order
// to avoid extra memory copies.
const new_memory = try self.allocator.alignedAlloc(T, alignment, new_capacity);
const to_move = self.items[index..];
@memcpy(new_memory[0..index], self.items[0..index]);
@memcpy(new_memory[index + count ..][0..to_move.len], to_move);
self.allocator.free(old_memory);
If the remap
can proceed without a copy, it does. Otherwise, the code allocates a new buffer, but it separately copies the parts of the original buffer before and after index
into the parts of the new buffer they need to go in. It also avoids copying any undefined space at the end of the old buffer, between the old length and capacity.
remap
isn't in any actual Zig release yet. It was checked into the master branch two days ago. There's no guarantee the final design will actually work like this, or that it'll even make it into the next Zig release at all. – user2357112 Commented 2 days ago