MemorySegment.ofAddress(...).reinterpret(...)

Brian S O'Neill bronee at gmail.com
Thu Jul 6 01:26:28 UTC 2023


The application is a high performance database which scales to support 
very large cache sizes with very little GC overhead. The database can 
operate in pure "in memory" mode, or be backed by a file, or be memory 
mapped, or be backed by a block device using O_DIRECT.

The bulk of the cache is allocated up front via mmap(anonymous), and 
page references into the cache are just plain long pointers. The cache 
can grow over time, and so not all pointers refer to the same region.

The critical operations are memory copies and accessing primitive types: 
MemorySegment.get/set(JAVA_BYTE, etc). Memory copies are performed 
between pages and also to/from Java byte arrays.

I could replace all pointer references with MemorySegment references 
(with great difficulty), but this would bloat the total heap size and 
increase GC overhead.

Currently I'm seeing a 3% performance regression using the foreign 
memory API compared to using Unsafe. One trick that I'm using is to 
refer to the entire address space using a static final field: ALL = 
MemorySegment.NULL.reinterpret(Long.MAX_VALUE). I don't know if this has 
any overhead or not. It seems like access to it should be completely 
unchecked.

For memory copies I can try copying to/from the "ALL" segment, in which 
case I don't need to allocate temporary MemorySegments at all. I'll 
report back with my findings. Perhaps I just really need a convenient 
reference to all memory, unchecked, and with low overhead.


On 2023-07-05 04:12 PM, Jorn Vernee wrote:
> Hello,
> 
> The usual way of attaching a size to a memory segment would be through a 
> target address layout [1]. MS::reinterpret is meant for cases where the 
> layout of the pointee is not statically known (and can not be captured 
> with a memory layout). But, both cases assume you're reading/writing 
> MemorySegments directly, instead of going through longs. Are neither of 
> these an option for you? Could you explain your use case a bit more?
> 
> I think we briefly considered having multiple MS::ofAddress overloads. 
> IIRC we decided against it, because the current MS::ofAddress is not a 
> restricted method, but, an overload that sets the size of the returned 
> segment would need to be restricted since the segment would be 
> accessible. So, adding more overloads would create a split between them 
> in terms of restricted-ness, which is not great.
> 
> I'll also note that, someone could define a utility method that fuses 
> the two operations, e.g.:
> 
> static MemorySegment longToSizedSegment(long baseAddress, long byteSize) {
>      return MemorySegment.ofAddress(baseAddress).reinterpret(byteSize);
> }
> 
> That is to say: I think we have the right primitives available in the 
> API. Though, your experience is a useful data point. We might want to 
> add some useful methods in the future if we see enough demand for them.
> 
> Thanks,
> Jorn
> 
> [1]: 
> https://download.java.net/java/early_access/jdk21/docs/api/java.base/java/lang/foreign/AddressLayout.html#withTargetLayout(java.lang.foreign.MemoryLayout)
> 
> On 06/07/2023 00:19, Brian S O'Neill wrote:


More information about the panama-dev mailing list