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