<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p>Hi Daniele,</p>
    <p>The first suggestion would be to use a `final static` field as a
      holder for the VarHandle. This is the same as what happens with
      MethodHandles - the JVM can apply more optimizations if the
      VarHandle is a known constant.</p>
    <p>Alternatively, you can just use
      `MemorySegment::setAtIndex(ValueLayout.JAVA_INT, index)`, which
      will do the right thing, with the correct performance model.</p>
    <p>Secondly, note that your benchmark is heavily dependent on
      On-Stack-Replacement - that is, the method being optimized is the
      same one being executed. This sometimes can lead to suboptimal
      optimizations (which is one of the things JMH tries to avoid). Not
      sure how much that would impact in this case.</p>
    <p>We do have JMH benchmarks with mapped buffers:</p>
    <p><a class="moz-txt-link-freetext" href="https://github.com/openjdk/panama-foreign/blob/foreign-memaccess%2Babi/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java">https://github.com/openjdk/panama-foreign/blob/foreign-memaccess%2Babi/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java</a></p>
    <p>These show that memory segment access is as fast as byte buffer
      and/or Unsafe.<br>
    </p>
    <p>Thanks<br>
      Maurizio</p>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 28/10/2022 22:59, Daniele Guiducci
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAPW=quiaQg-OL7yOxgLfCuDtmAh-Ly1hPyZ2Wsxs03Hr=4uc+w@mail.gmail.com">
      
      <div dir="ltr">
        <div dir="ltr" data-smartmail="gmail_signature">
          <div dir="ltr">
            <div dir="ltr">
              <div>Hello,</div>
              <div><br>
              </div>
              <div>I'm running some tests comparing the performance of
                the various methods available to set a value in a
                MemorySegment.</div>
              <div><br>
              </div>
              <div>Based on a simple benchmark I wrote, VarHandle seems
                to be the slowest one, which is odd to me.</div>
              <div><br>
              </div>
              <div>This is the output of the benchmark:</div>
              <div>
                <ul>
                  <li>Manual offset set; Total time 147<br>
                  </li>
                  <li>VarHandle; Total time 3197<br>
                  </li>
                  <li>Method Handle; Total time 767<br>
                  </li>
                </ul>
              </div>
              <div>I'm testing this from a MacOS Air M2 (arm chip). I
                also ran other tests trying to warm up the virtual
                machine but I didn't get much improvements.</div>
              <div><br>
              </div>
              <div>And this is the code. I didn't use microbenchmarking
                but the result wouldn't change:</div>
              <div><font face="monospace">public static void
                  main(String[] args) throws Throwable {<br>
                          long elementCount = 200_000_000;<br>
                          var testFile = Path.of("test.data");<br>
                          FileChannel fc = FileChannel.open(testFile,<br>
                                  StandardOpenOption.CREATE,<br>
                                  StandardOpenOption.READ,<br>
                                  StandardOpenOption.WRITE<br>
                          );<br>
                          var segment =
                  fc.map(FileChannel.MapMode.READ_WRITE, 0, elementCount
                  * </font><span style="font-family:monospace">Integer.BYTES</span><span style="font-family:monospace">,
                  MemorySession.global());</span></div>
              <div><font face="monospace"><br>
                          MemoryLayout memoryLayout =
                  MemoryLayout.sequenceLayout(<br>
                                  elementCount,
                  ValueLayout.JAVA_INT.withName("counter")<br>
                          );<br>
                  <br>
                          VarHandle varHandle =
                  memoryLayout.varHandle(MemoryLayout.PathElement.sequenceElement());<br>
                          var arrayMethodHandle =
memoryLayout.byteOffsetHandle(MemoryLayout.PathElement.sequenceElement());<br>
                  <br>
                  <br>
                          // Init file Manually<br>
                          for (int i = 0; i < elementCount; i++) {<br>
                              segment.set(ValueLayout.JAVA_INT, i * 4L,
                  99);<br>
                          }<br>
                  <br>
                          long startTime;<br>
                  <br>
                  <br>
                          startTime = System.currentTimeMillis();<br>
                          for (int i = 0; i < elementCount; i++) {<br>
                              segment.set(ValueLayout.JAVA_INT, i *
                  Integer.BYTES, 33);<br>
                          }<br>
                          System.out.println("Manual offset set; Total
                  time " + (System.currentTimeMillis() - startTime));<br>
                  <br>
                  <br>
                          startTime = System.currentTimeMillis();<br>
                          for (int i = 0; i < elementCount; i++) {<br>
                              varHandle.set(segment, (long) i, 10);<br>
                          }<br>
                          System.out.println("VarHandle; Total time " +
                  (System.currentTimeMillis() - startTime));<br>
                  <br>
                  <br>
                          startTime = System.currentTimeMillis();<br>
                          for (int i = 0; i < elementCount; i++) {<br>
                              // User method handle to calculate offset<br>
                              long offset = (long)
                  arrayMethodHandle.invokeExact((long) i);<br>
                              segment.set(ValueLayout.JAVA_INT, offset,
                  10);<br>
                          }<br>
                          System.out.println("Method Handle; Total time
                  " + (System.currentTimeMillis() - startTime));<br>
                  <br>
                          fc.close();<br>
                          Files.delete(testFile);<br>
                      }</font><br>
              </div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
  </body>
</html>