MemorySegment.ofAddress(...).reinterpret(...)
Brian S O'Neill
bronee at gmail.com
Thu Jul 6 02:40:08 UTC 2023
When I copy against the "ALL" segment, the overall performance
regression goes from 3% to 2%. How I can I reduce this overhead further?
What I really want is something like the Unsafe class. It's simple,
direct, and efficient. Unfortunately, it's going away at some point.
On 2023-07-05 06:26 PM, Brian S O'Neill wrote:
> 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