<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>Clarification:</p>
<p>`segment` and `segment2` are equals (as in
`segment.equals(segment2)` returns true).</p>
<p>They feature the same lifetime, so they can be compared. But
`segment2` is a fresh new instance which points at the same memory
as `segment`.</p>
<p>Back to the original question: Sergio, can you please clarify
what you mean by "copy" ? The examples Remi provided do not really
copy anything, they just alternate between a memory segment and a
byte buffer view of the same region of memory.</p>
<p>It would be useful to have a pointer to some existing code using
Unsafe, so that we can better understand each other.</p>
<p>Cheers<br>
Maurizio<br>
</p>
<div class="moz-cite-prefix">On 27/12/2024 14:33, Remi Forax wrote:<br>
</div>
<blockquote type="cite" cite="mid:834813676.33803000.1735310025587.JavaMail.zimbra@univ-eiffel.fr">
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000">
<div><br>
</div>
<div><br>
</div>
<hr id="zwchr" data-marker="__DIVIDER__">
<div data-marker="__HEADERS__">
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From:
</b>"Remi Forax" <a class="moz-txt-link-rfc2396E" href="mailto:forax@univ-mlv.fr"><forax@univ-mlv.fr></a><br>
<b>To: </b>"Sergio Selos"
<a class="moz-txt-link-rfc2396E" href="mailto:sergio.selos.chicago@gmail.com"><sergio.selos.chicago@gmail.com></a><br>
<b>Cc: </b>"panama-dev" <a class="moz-txt-link-rfc2396E" href="mailto:panama-dev@openjdk.org"><panama-dev@openjdk.org></a><br>
<b>Sent: </b>Friday, December 27, 2024 2:52:17 PM<br>
<b>Subject: </b>Re: Garbage problem migrating from
sun.misc.Unsafe to FFM API<br>
</blockquote>
</div>
<div data-marker="__QUOTED_TEXT__">
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000">
<div>I do not think you need pooling,<br>
</div>
<div>if the ByteBuffer is created from a MemorySegment, it
keeps a reference to the MemeorySegment<br>
</div>
<br>
<div>
<div style="background-color: #ffffff; color: #080808;">
<pre style="font-family: 'JetBrains Mono',monospace; font-size: 9.8pt;"><span style="color: #0033b3;">var </span><span style="color: #000000;">segment </span>= <span style="color: #000000;">Arena</span>.<em>global</em>().allocate(<span style="color: #1750eb;">8192</span>);
<span style="color: #0033b3;">var </span><span style="color: #000000;">buffer </span>= <span style="color: #000000;">segment</span>.asByteBuffer();</pre>
...
<pre style="font-family: 'JetBrains Mono',monospace; font-size: 9.8pt;"><span style="color: #0033b3;">var </span><span style="color: #000000;">segment2 </span>= <span style="color: #000000;">MemorySegment</span>.<span style="font-style: italic;">ofBuffer</span>(<span style="color: #000000;">buffer</span>);
<span style="font-style: italic;">assertSame(</span><span style="color: #000000;">segment, </span><span style="color: #000000;">segment2</span>); // should be ok !</pre>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>It's not :( t's a MemorySegment with the same address but
not the same memory segment,<br data-mce-bogus="1">
</div>
<div>so you have to hope that the VM is able to do escape
analysis on the result of ofBuffer().<br data-mce-bogus="1">
</div>
<div><br data-mce-bogus="1">
</div>
<div>Rémi</div>
<div><br>
</div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000">
<div><br>
</div>
<br>
<hr id="zwchr">
<div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From:
</b>"Sergio Selos"
<a class="moz-txt-link-rfc2396E" href="mailto:sergio.selos.chicago@gmail.com"><sergio.selos.chicago@gmail.com></a><br>
<b>To: </b>"Remi Forax" <a class="moz-txt-link-rfc2396E" href="mailto:forax@univ-mlv.fr"><forax@univ-mlv.fr></a><br>
<b>Cc: </b>"panama-dev"
<a class="moz-txt-link-rfc2396E" href="mailto:panama-dev@openjdk.org"><panama-dev@openjdk.org></a><br>
<b>Sent: </b>Friday, December 27, 2024 1:12:52 PM<br>
<b>Subject: </b>Re: Garbage problem migrating from
sun.misc.Unsafe to FFM API<br>
</blockquote>
</div>
<div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<div dir="ltr">Thanks for your answer, Remi.<br>
<div>> Then I think that the idea if you want to
minimize the garbage is to create the ByteBuffer
from a MemorySegment with asByteBuffer() so you
can then use ofBuffer() when you want the
MemorySegment back.</div>
<br>
<div>That approach could work, but ideally, we want
the same capability provided by sun.misc.Unsafe
today: the ability to work directly with external
ByteBuffers. Note that we’re not really using the
ByteBuffer itself but its underlying native memory
address. Perhaps I’m overlooking something, but it
seems the FFM API should offer a way to copy data
directly between native memory regions.</div>
<br>
<div>I also posted this question on StackOverflow
and it was suggested to pool a MemorySegment per
ByteBuffer. Unfortunately I'm afraid that will be
a show-stopper due to the extra lookup in the
critical path. For the record, the SO question is <a href="https://stackoverflow.com/questions/79311345/is-it-possible-to-copy-from-native-memory-to-a-bytebuffer-using-the-new-ffm-api" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">https://stackoverflow.com/questions/79311345/is-it-possible-to-copy-from-native-memory-to-a-bytebuffer-using-the-new-ffm-api</a><br>
<br>
All the best,</div>
<br>
<div>-Sergio</div>
</div>
<br>
<div class="gmail_quote gmail_quote_container">
<div dir="ltr" class="gmail_attr">On Fri, Dec 27,
2024 at 8:16 AM Remi Forax <<a href="mailto:forax@univ-mlv.fr" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">forax@univ-mlv.fr</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<div>Hello,<br>
</div>
<div>are you using an older jdk than 22,
MemorySegment.ofBuffer() should only takes a
ByteBuffer [1] ?<br>
</div>
<br>
<div>Then I think that the idea if you want to
minimize the garbage is to create the
ByteBuffer from a MemorySegment with
asByteBuffer() so you can then use
ofBuffer() when you want the MemorySegment
back.<br>
</div>
<br>
<div>That said, i would love to have methods
like read() and write() to take
MemorySegment instead of ByteBuffer because
for my students the ByteBuffer API is an
useless complication (you have to understand
how the indexes work) when doing serious IO.
Having API closest to the C ones would help
a lot.<br>
</div>
<br>
<div>Rémi<br>
</div>
<br>
<div>[1] <a href="https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/foreign/MemorySegment.html#ofBuffer(java.nio.Buffer)" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/foreign/MemorySegment.html#ofBuffer(java.nio.Buffer)</a><br>
</div>
<br>
<hr id="m_-7708128969535918099zwchr">
<div>
<blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><b>From:
</b>"Sergio Selos" <<a href="mailto:sergio.selos.chicago@gmail.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">sergio.selos.chicago@gmail.com</a>><br>
<b>To: </b>"panama-dev" <<a href="mailto:panama-dev@openjdk.org" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">panama-dev@openjdk.org</a>><br>
<b>Sent: </b>Friday, December 27, 2024
2:05:24 AM<br>
<b>Subject: </b>Garbage problem migrating
from sun.misc.Unsafe to FFM API<br>
</blockquote>
</div>
<div>
<blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt">
<div dir="ltr">Hello,<br>
<div>We have a project using
sun.misc.Unsafe that we are migrating
to the new FFM API. The project is at
<a href="https://www.github.com/coralblocks/CoralRing" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">https://www.github.com/coralblocks/CoralRing</a><br>
</div>
<br>
<div>For our particular systems (mostly
financial low latency systems) it is
important not to create any garbage
(temp discarded instances) when
receiving a message.</div>
<br>
<div>We encountered an issue when
copying from native memory straight
into a direct ByteBuffer using the FFM
API.</div>
<br>
<div>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.</div>
<br>
<div>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?</div>
<br>
<div>Maybe there is already a way and we
are just unaware how to do it.</div>
<br>
<div>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.</div>
<br>
<div>Thanks and let me know if you need
any more details about this and/or if
I can help with anything.</div>
<br>
<div>All the best,</div>
<br>
<div>-Sergio</div>
<br>
<div>// With sun.misc.Unsafe:</div>
<div>@Override<br>
public void getByteBuffer(long
address, ByteBuffer dst, int len) {<br>
if (!dst.isDirect()) {<br>
throw new
RuntimeException("getByteBuffer can
only take a direct byte buffer!");<br>
}<br>
try {<br>
long dstAddress = (long)
addressField.get(dst); // get the
memory address of this ByteBuffer<br>
dstAddress += dst.position();
// adjust the address for the
ByteBuffer current position<br>
unsafe.copyMemory(address,
dstAddress, len); // copy over<br>
dst.position(dst.position() +
len); // adjust the ByteBuffer
position to reflect the copy operation<br>
} catch(Exception e) {<br>
throw new RuntimeException(e);<br>
}<br>
}<br>
</div>
<br>
<div>// With FFM API:</div>
<div>@Override<br>
public void getByteBuffer(long
address, ByteBuffer dst, int len) {<br>
if (!dst.isDirect()) {<br>
throw new
RuntimeException("getByteBuffer can
only take a direct byte buffer!");<br>
}</div>
<div><br>
long offset = address -
this.address; // offset in our
'segment'<br>
<br>
try (Arena arena =
Arena.ofConfined()) { // <====
probably creating a temp object here
too<br>
// Wrap the destination
ByteBuffer in a temporary segment<br>
// This segment's data starts
at dst.position()<br>
MemorySegment dstSegment =
MemorySegment.ofBuffer(dst, arena); //
<====== temp memory segment object<br>
<br>
// Copy from 'segment' at
'offset' → dstSegment at offset 0 →
length = 'len'<br>
dstSegment.copyFrom(this.segment,
offset, 0, len);<br>
}<br>
dst.position(dst.position() +
len);<br>
}<br>
</div>
<br>
<br>
<br>
<div> </div>
</div>
</blockquote>
</div>
</div>
</div>
</blockquote>
</div>
</blockquote>
</div>
</div>
<br>
</blockquote>
</div>
</div>
</blockquote>
</body>
</html>