<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div><span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">Hi
</span><span style="font-family: "Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, "system-ui", Roboto, "Helvetica Neue", sans-serif; font-size: 14.6667px; color: rgb(36, 36, 36); background-color: rgb(255, 255, 255);">Rémi</span><span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">,<br>
<br>
I understand how the code is supposed to work (interesting solution!) but actually seeing how things are inlined/folded in reality is often hard. What you could do is to try and log inlining. Jorn has written some excellent articles about this:<br>
<br>
<a href="https://jornvernee.github.io/methodhandles/2024/01/19/methodhandle-primer.html#method-handle-inlining" id="LPlnk">https://jornvernee.github.io/methodhandles/2024/01/19/methodhandle-primer.html#method-handle-inlining</a><br>
<a href="https://jornvernee.github.io/hotspot/jit/2023/08/18/debugging-jit.html#3-printing-inlining-traces" id="LPlnk">https://jornvernee.github.io/hotspot/jit/2023/08/18/debugging-jit.html#3-printing-inlining-traces</a></span></div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">I hope that can give you some additional clues what is going on. If not, I hope someone else with more knowledge
 on the compiler can point you in the right direction.</span>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Best, Per Minborg</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> panama-dev <panama-dev-retn@openjdk.org> on behalf of Remi Forax <forax@univ-mlv.fr><br>
<b>Sent:</b> Wednesday, April 24, 2024 8:37 AM<br>
<b>To:</b> hotspot compiler <hotspot-compiler-dev@openjdk.java.net><br>
<b>Cc:</b> panama-dev <panama-dev@openjdk.org><br>
<b>Subject:</b> Weird performance behavior involving VarHandles</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">Hello,<br>
i'm trying to build an API on top of the foreign memory API and i've found a performance difference i'm not able to explain.<br>
<br>
I'm using a guardWithTest to try to provide a simple way to access a VarHandle on a MemoryLayout without having to declare each VarHandle by hand,<br>
so instead of<br>
<br>
  private static final StructLayout LAYOUT = MemoryLayout.structLayout(<br>
      ValueLayout.JAVA_INT.withName("x"),<br>
      ValueLayout.JAVA_INT.withName("y")<br>
  );<br>
<br>
  private static final VarHandle HANDLE_X =<br>
      LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("x"));<br>
  private static final VarHandle HANDLE_Y =<br>
      LAYOUT.varHandle(MemoryLayout.PathElement.groupElement("y"));<br>
<br>
I want something like<br>
<br>
  private static final MethodHandle MH = guardWithTest(<br>
      TEST.bindTo("x"),<br>
      dropArguments(constant(VarHandle.class, HANDLE_X), 0, String.class),<br>
      guardWithTest(<br>
          TEST.bindTo("y"),<br>
          dropArguments(constant(VarHandle.class, HANDLE_Y), 0, String.class),<br>
          BOOM<br>
      ));<br>
<br>
  (TEST does an == on the strings and BOOM throws an exception)<br>
<br>
which if called with "x" returns the VarHandle for "x" and if called with "y" returns the VarHandle for "y".<br>
<br>
<br>
Now if I try to benchmark the performance with JMH,<br>
<br>
  private final MemorySegment segment = Arena.ofAuto().allocate(LAYOUT);<br>
<br>
  @Benchmark<br>
  public int control() {<br>
    var x = (int) HANDLE_X.get(segment, 0L);<br>
    var y = (int) HANDLE_Y.get(segment, 0L);<br>
    return x + y;<br>
  }<br>
<br>
  @Benchmark<br>
  public int gwt2_methodhandle() throws Throwable {<br>
    var x = (int) ((VarHandle) MH.invokeExact("x")).get(segment, 0L);<br>
    var y = (int) ((VarHandle) MH.invokeExact("y")).get(segment, 0L);<br>
    return x + y;<br>
  }<br>
<br>
I get<br>
<br>
Benchmark                               Mode  Cnt  Score   Error  Units<br>
ReproducerBenchmarks.control            avgt    5  1.250 ± 0.024  ns/op<br>
ReproducerBenchmarks.gwt2_methodhandle  avgt    5  1.852 ± 0.024  ns/op<br>
<br>
and I don't understand why there is a difference in performance because for c2, the strings "x" and "y" are constant so the corresponding VarHandles should be constant thus optimized the same way.<br>
<br>
The full benchmark is available here:<br>
  <a href="https://raw.githubusercontent.com/forax/memory-mapper/master/src/main/java/com/github/forax/memorymapper/bench/ReproducerBenchmarks.java">
https://raw.githubusercontent.com/forax/memory-mapper/master/src/main/java/com/github/forax/memorymapper/bench/ReproducerBenchmarks.java</a><br>
<br>
regards,<br>
Rémi<br>
<br>
</div>
</span></font></div>
</body>
</html>