Garbage problem migrating from sun.misc.Unsafe to FFM API

Sergio Selos sergio.selos.chicago at gmail.com
Fri Dec 27 01:05:24 UTC 2024


Hello,

We have a project using sun.misc.Unsafe that we are migrating to the new
FFM API. The project is at https://www.github.com/coralblocks/CoralRing

For our particular systems (mostly financial low latency systems) it is
important not to create any garbage (temp discarded instances) when
receiving a message.

We encountered an issue when copying from native memory straight into a
direct ByteBuffer using the FFM API.

Using sun.misc.Unsafe, copying from memory to a ByteBuffer can be done
without creating temporary objects and garbage collector overhead. However,
with the FFM API, achieving the same does not seem currently possible
without generating garbage via a call to MemorySegment.ofBuffer.

Does the FFM dev team plan to address this issue and provide a garbage-free
way to perform this copy, like we currently can with sun.misc.Unsafe?

Maybe there is already a way and we are just unaware how to do it.

Below the current code we have with sun.misc.Unsafe, which does not produce
any garbage, and the only way we are aware of to do it with the FFM API,
which produces garbage.

Thanks and let me know if you need any more details about this and/or if I
can help with anything.

All the best,

-Sergio

// With sun.misc.Unsafe:
@Override
public void getByteBuffer(long address, ByteBuffer dst, int len) {
    if (!dst.isDirect()) {
        throw new RuntimeException("getByteBuffer can only take a direct
byte buffer!");
    }
    try {
        long dstAddress = (long) addressField.get(dst); // get the memory
address of this ByteBuffer
        dstAddress += dst.position(); // adjust the address for the
ByteBuffer current position
        unsafe.copyMemory(address, dstAddress, len); // copy over
        dst.position(dst.position() + len); // adjust the ByteBuffer
position to reflect the copy operation
    } catch(Exception e) {
        throw new RuntimeException(e);
    }
}

// With FFM API:
@Override
public void getByteBuffer(long address, ByteBuffer dst, int len) {
    if (!dst.isDirect()) {
        throw new RuntimeException("getByteBuffer can only take a direct
byte buffer!");
    }

    long offset = address - this.address; // offset in our 'segment'

    try (Arena arena = Arena.ofConfined()) { // <==== probably creating a
temp object here too
        // Wrap the destination ByteBuffer in a temporary segment
        // This segment's data starts at dst.position()
        MemorySegment dstSegment = MemorySegment.ofBuffer(dst, arena); //
<====== temp memory segment object

        // Copy from 'segment' at 'offset' → dstSegment at offset 0 →
length = 'len'
        dstSegment.copyFrom(this.segment, offset, 0, len);
    }
    dst.position(dst.position() + len);
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20241226/86eb65a7/attachment.htm>


More information about the panama-dev mailing list