Arena/Segment allocator and zero initialized MemorySegment

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Jun 5 17:51:44 UTC 2024


On 05/06/2024 18:25, Pedro Lamarão wrote:

> Also, as this discussion suggests, what appears to be a universal 
> interface may actually not be universal at all, and perhaps it is best 
> to have libraries define their own allocator interfaces and see what 
> emerges from that.

This is the thing we keep (re)learning when thinking about allocators in 
FFM. It is tempting to hardwire something to cater specific needs, but 
in reality specific libraries will work with very specific set of 
constraints, so our best bet is to somehow support such things to be 
built on top.

Now, this is orthogonal to the original question which was about 
advertizing zeroing properties of an allocator. What we’re seeing there 
is the (unavoidable) consequence of the (unavoidable) decision of not 
exposing (by default, at least) non-zeroing memory allocation 
primitives. E.g. it is easy to write a zeroing allocator if you have a 
non-zeroing one (as the latter is clearly more primitive than the 
former). But it wouldn’t have been safe to expose non-zeroing allocators 
in the front door allocation API. This set of constraints has led us to 
SegmentAllocator being the way it is today, where we make no assumption 
on what the “correct” behavior for SegmentAllocator::allocate should be. 
For Arenas that are provided by the JDK, the answer has to be “zeroing”. 
But users are (and should!) be able to define allocators/arenas that do 
no zero, if they have compelling use cases where zeroing would add too 
much overhead.

Should we have an extra method in SegmentAllocator which states what’s 
the zeroing policy for the allocator?

It’s certainly cheap to add, but:

  * users will forget to override that (esp. given SegmentAllocator is a
    functional interface)
  * it only addresses /one/ dimension in which a given allocator is
    special - are there others? (e.g. disjointness of returned segments,
    etc)
  * another approach could be for clients that do want guaranteed
    zeroing to always call MS::fill, and rely on C2 to eliminate the
    redundant memset (after all Unsafe::setMemory is an intrinsics).
    This is hard to achieve, but would probably lead to a better
    long-term path, where we can stop worrying about duplicate zeroing
    (as happens for on-heap arrays). At this point having the predicate
    on |SegmentAllocator| woudn’t add too much.

For all these reasons, I’m slightly against adding new methods to 
SegmentAllocator. Of course if this requests turned out to be a very 
common one I could reconsider of course.

Last, note that there’s a workaround, even though it might not look too 
pretty. Let’s say that you know that you only allocate 1024 bytes tops. 
Then you can do like so:

|MemorySegment allocateAndZero(SegmentAllocator allocator, long size) { 
class Holder { static MemorySegment ZERO = MemorySegment.ofArray(new 
byte[1024]); } // todo: check that `size < 1024` return 
allocator.allocateFrom(JAVA_BYTE, Holder.ZERO, JAVA_BYTE, 0, size); } |

Note that this uses |allocateFrom| to allocate a memory segment of given 
size, and then bulk copy (a part of) the “zero segment” on top of it. 
This won’t perform double zeroing, because 
|SegmentAllocator::allocateFrom| tries to avoid that also. The only 
difference is that we’re using “Unsafe::copyMemory” instead of 
“Unsafe::setMemory” to zero the memory (but both should perform roughly 
the same, as they are both intrinsics that support vectorized 
instructions). It’s not pretty, but maybe could be ok while we wait for 
deeper “duplicate zero memset” avoidance?

Maurizio

​
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20240605/5c81e961/attachment.htm>


More information about the panama-dev mailing list