<!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>