Arena/Segment allocator and zero initialized MemorySegment

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Jun 5 15:36:47 UTC 2024


On 05/06/2024 16:09, forax at univ-mlv.fr wrote:
> The old library uses 
> Unsafe.allocateMemory()/reallocateMemory()/setMemory()/copyMemory()/freeMemory() 
> and uses the finalizer mechanism for the safe but late deallocation.
>
> For now, the new library do not try to reallocate, so when it needs to 
> grow the storage, it asks for a new MemorySegment and copy the data.
> It seems I should use an Arena instead of a SegmentAllocator because 
> two subsequent calls to allocate() should not return the same address, 
> but i have two reasons to not using it. Arena does not garantee that 
> the storage is zeroed and it keeps the storage until the Arena is 
> closed so if the list grows several times, it will keep all previous 
> segments in memory.

There's also a bigger problem you have with subsequent calls to a 
generic SegmentAllocator: you have no guarantee the lifetimes of the two 
segments is compatible. So, the list could be created initially with a 
lifetime, but then you ask the allocator for another segment and you get 
something with a different lifetime.

If you want to use Arena, then a better approach would be to allocate 
the list in "slabs", and avoid the copy. E.g. you start of with a single 
segment of size N (where N is some multiple of the element type size). 
If you need to grow you allocate another segment of size N, and so on. 
Then you add some logic to "pick the right" segment given the accessed 
index. That would be the most natural way to implement what you are 
after using Arenas.

I understand you want to have same semantics as Arrays.copyOf. If that's 
the case, perhaps using raw malloc/free/realloc and just replace unsafe 
with such method handles would be a better way to go. You can even (with 
MemorySegment::reinterpret) attach a lifetime on the malloc/realloc 
segment, if you wanted to. E.g. your API could:

* take an Arena (the lifetime that should be used for the collection)
* use a method handle to call malloc, then reinterpret the resulting 
segment with initial size and provided arena. The reinterpret can also 
pass a "cleanup" action which might be useful to get free the "current 
segment" (e.g. the segment currently associated with the collection)
* when more space is needed, we call realloc, and reinterpret the 
resulting segment, same as before. This will set a new backing segment 
on the current collection.

Note that here you are not really doing any allocation using 
Arena::allocate. Instead you'd be performing what we call "external 
allocation" - e.g. you use a native API to do the allocation, then wrap 
the resulting segment with given size and lifetime.

This would be working more or less like what you had with Unsafe, but 
with two advantages:

* clients can now pick their own Arena. So could use `Arena::ofAuto` if 
they are ok with GC-driven deallocation, but could also use a confined 
arena with TWR
* after the user-provided Arena is closed, the collection backing the 
segment will no longer be accessible, and that's guaranteed by the API


>
> As far as i understand what an Arena is, an Arena is virtual, it's not 
> contiguous memory*, so supporting deallocation is possible (i'm not 
> saying it should) and having a way to ask for a zero initialized 
> MemorySegement is also something possible (again, not saying it should).

While asking for _really really_ zero initialized segment is something 
that can be done, supporting deallocation of lone segments in an arena 
is not what the Arena API is about. All segments in the arena share the 
same lifetime, so they are either all alive, or all dead. This is what 
makes it possible to deal with cases where you have pointers in a struct 
referring to another struct safely (because if both structs came from 
the same arena, it's easy to prove everything works as it should). Once 
you start deallocating only _some_ things inside an arena, you are back 
to the same usability issues that malloc/free have (meaning that whether 
an Arena is alive or not, it doesn't really matter much, given that 
segments can go away at any time). So no, that's not something that I'd 
consider "possible", as it would violate the very essence of the 
contract that Arena is trying to establish.

Maurizio





More information about the panama-dev mailing list