Propose 2 new methods for MemorySegment

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Jun 16 08:43:19 UTC 2021


I see what you mean.

I wonder if this use case isn't already partially covered by 
MemoryAddress::segmentOffset.

E.g. can you do:

long otherOffset = segment.address().segmentOffset(otherSegment);

Then it should be easy to check if the offset is within the bounds of 
"otherSegment" ?

(Note that the method already throws if you try to compare addresses and 
segments that are mismatched - e.g. on-heap vs. off-heap).

Not saying a more direct API is ruled out, just pointing out what we 
have to see if it can be used.

Maurizio


On 16/06/2021 02:37, leerho wrote:
> In working on https://github.com/openjdk/panama-foreign/pull/555, which is
> the PR for Memory Segment Efficient Array Handling, I discovered that there
> are two methods that would be very useful beyond copying arrays, but useful
> in other types of data movement operations between MemorySegments.
>
> I'd like to draw attention to the opening Javadoc of the
> *MemorySegment::copyFrom(MemorySegment)* method:
>
> 1. Performs a bulk copy from given source segment to this segment. More
>> specifically, the bytes at offset 0 through src.byteSize() - 1 in the
>> source segment are copied into this segment at offset 0 through src.byteSize()
>> - 1. If the source segment overlaps with this segment, then the copying
>> is performed as if the bytes at offset 0 through src.byteSize() - 1 in
>> the source segment were first copied into a temporary segment with size
>> bytes, and then the contents of the temporary segment were copied into
>> this segment at offset 0 through src.byteSize() - 1.
>>
>> 2. The result of a bulk copy is unspecified if, in the uncommon case, the
>> source segment and this segment do not overlap, but refer to overlapping
>> regions of the same backing storage using different addresses. For example,
>> this may occur if the same file is mapped
>> <#mapFile(java.nio.file.Path,long,long,java.nio.channels.FileChannel.MapMode,jdk.incubator.foreign.ResourceScope)> to
>> two segments.
>>
> The first paragraph is a guarantee that even if two descendant segments
> have an overlapping region with a parent segment that the copy operation
> will work properly.  This is similar to the guarantee of System.arrayCopy()
>
> The second paragraph refers to memory-mapped files.  However, let's examine
> the following scenario:
>
>     - A hierarchy of Memory Segments where two descendant segments may
>     overlap a region of the parent segment.
>     - The elements of the segments are more complex than Java primitives
>     (thus, PR 555 doesn't apply).
>     - The user wishes to copy a region of elements from one of the
>     descendant segments to the other descendant segment.
>     - The user only has the two descendant segments in hand and does not
>     have access to the parent segment.
>
> With the current MemorySegment API, the descendant segments are blind to
> the overlap, to wit:
>
>     - The user cannot determine if an overlap exists.
>     - Or, if an overlap exists where the overlap is with respect to the two
>     segments in hand.
>
> In order to ensure that corruption doesn't occur during the copy, the user
> must create a temporary duplicate of the destination segment, copy the data
> into the duplicate, then copy the duplicate into the original destination
> segment.  This can be expensive in time and space.
>
> If, however, the user can determine that an overlap exists, and where the
> overlap occurs, the copy operation can be done safely, with no additional
> storage, by properly choosing the direction of the iterative copy.
>
> To solve this, the user doesn't need access to the parent segment (this
> could be for security reasons), but could use these two methods:
>
>     - MemorySegment::boolean isSameBaseResource(MemorySegment other);
>     The intent is to reveal if *this* segment and the *other* segment share
>     a common ancestor segment.  It could also be extended to determine if the
>     two segments share the same memory-mapped file (a true resource), thus
>     possibly removing the caveat in paragraph 2 above.
>
>
>     - MemorySegment::long baseResourceOffsetBytes();
>     This would return the offset in bytes of the start of this segment from
>     the start of the highest common segment (or resource).
>
> With this information, the user can easily design a safe, efficient, and
> fast data copy method for moving arbitrary elements from one segment to
> another with the same guarantee as System.arrayCopy().
>
> *Evidence*
> See (copySwap(...)
> <https://github.com/leerho/PanamaLocal/blob/main/src/main/java/org/apache/datasketches/panama/MemoryCopy.java#L667-L703>).
> Before I had access to the new MemorySegment::void copyFrom(MemorySegment,
> MemoryLayout, MemoryLayout), I had to design a proxy routine that would do
> the copy (with swap) correctly, especially in the case where the two
> segments overlapped. Note lines 682, 683 where I create a temporary
> segment. If I had the above two methods, this extra copy operation would
> not be needed.
>
> For exactly the above reasons, some years ago we implemented similar
> methods in our DataSketches Memory Component
> <https://datasketches.apache.org/api/memory/snapshot/apidocs/index.html>.
> Specifically, in the class *WritableMemory*, the methods *getRegionOffset()*
> and *isSameResource(that).*
>
> Lee.


More information about the panama-dev mailing list