<div dir="ltr"><div class="gmail_default" style="font-family:arial,sans-serif">Yes, I know.  Though I provided "the rest of the code" in my email.  But I should have just used JMH in the first place.</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">I tested with JMH on two machines and got very different results..</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">To summarize:</div><div class="gmail_default" style="font-family:arial,sans-serif">macOS Intel i7 JDK 20.0.1  mask: 1.082 ops/s  modulo: 1.080 ops/s</div><div class="gmail_default" style="font-family:arial,sans-serif">macOS Intel i7 JDK 17.0.7  mask: 1.040 ops/s  modulo: 0.815 ops/s</div><div class="gmail_default" style="font-family:arial,sans-serif"><div class="gmail_default">Linux Intel i5 JDK 20.0.1  mask: 0.759 ops/s  modulo: 1.070 ops/s</div><div class="gmail_default">Linux Intel i5 JDK 17.0.8  mask: 0.738 ops/s  modulo: 1.039 ops/s<br></div></div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">macOS:</div><div class="gmail_default" style="font-family:arial,sans-serif">CPU: Quad-Core Intel Core i7-7700K</div><div class="gmail_default" style="font-family:arial,sans-serif"><div class="gmail_default">OpenJDK 64-Bit Server VM Zulu17.42+19-CA (build 17.0.7+7-LTS, mixed mode, sharing)</div><div class="gmail_default"><div class="gmail_default">OpenJDK 64-Bit Server VM Zulu20.30+11-CA (build 20.0.1+9, mixed mode, sharing)</div><div class="gmail_default"><br></div></div><div class="gmail_default">Linux:</div><div class="gmail_default">CPU: 12th Gen Intel® Core™ i5-1245U × 12</div><div class="gmail_default">OpenJDK 64-Bit Server VM Corretto-17.0.8.7.1 (build 17.0.8+7-LTS, mixed mode, sharing)</div><div class="gmail_default">OpenJDK 64-Bit Server VM Temurin-20.0.1+9 (build 20.0.1+9, mixed mode, sharing)<br></div><div class="gmail_default"><br></div><div class="gmail_default">On Linux the results are the opposite of what I would expect.  Interestingly JDK 20.0.1 on macOS had no significant difference between the two methods, but on Linux it did.<br></div></div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">Regards,</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">Scott</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jul 22, 2023 at 11:24 AM Remi Forax <<a href="mailto:forax@univ-mlv.fr" target="_blank">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>Please use JMH for your performance tests, otherwise what you see may just be an artifact of the way you have written the rest of the code, not the code you want to test.<br></div><div><br></div><div>regards,<br></div><div>Rémi<br></div><div><br></div><hr id="m_-264628946560704258m_6680616230640764171zwchr"><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>"Scott Palmer" <<a href="mailto:swpalmer@gmail.com" target="_blank">swpalmer@gmail.com</a>><br><b>To: </b>"hotspot-dev" <<a href="mailto:hotspot-dev@openjdk.org" target="_blank">hotspot-dev@openjdk.org</a>><br><b>Sent: </b>Saturday, July 22, 2023 5:15:48 PM<br><b>Subject: </b>Unexpected performance of operator % vs &<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"><div class="gmail_default" style="font-family:arial,sans-serif">I hope this is the appropriate list for this question.</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">Given the following Java code to test if a number is even or odd I observed unexpected results.</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">boolean evenA = ((i % 2) == 0);</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">boolean evenB = ((i & 1) == 0);</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">I expect the bitwise AND to be the fastest, as modulo operations are generally slower. The masking operation should never take more CPU cycles than the modulo operation.<br></div><div class="gmail_default" style="font-family:arial,sans-serif">This in fact is true, but only until the code is JIT compiled, and then the performance flips and the modulo version is notably faster.</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">This remains the case for checking if 'i' is evenly divisible by 4, using (i % 4) vs (i & 3).  Only when I get to checking for divisibility by 8 using (i % 8) vs (i & 7) do I see the performance shift to masking's favour after JIT compiling.</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">I suspect there is an optimization somewhere in the JIT compiler that sees the modulo 2 pattern and outputs optimized code that is not in fact doing a modulo calculation.  What I don't understand is how it ends up faster than the bit-mask version.  The JIT compiler appears to be undoing my attempted optimization.</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">Am I making a mistake here (other than assuming what is faster before profiling)?</div><div class="gmail_default" style="font-family:arial,sans-serif">Is this something that could be improved/fixed in the compiler?</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">Regards,</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">Scott</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">My simple experiment:</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">  public static void main(String [] args) {<br>    for (int i = 0; i < 10; i++) {<br>      long start = System.nanoTime();<br>      long maskCount = mask();<br>      var maskTime = Duration.ofNanos(System.nanoTime()-start);<br>      System.out.printf("%d     mask method took: %s%n", maskCount, maskTime);<br>      start = System.nanoTime();<br>      long moduloCount = modulo();<br>      var moduloTime = Duration.ofNanos(System.nanoTime()-start);<br>      System.out.printf("%d  modulo method took: %s%n", moduloCount, moduloTime);<br>      System.out.println("fastest: " + ((maskTime.compareTo(moduloTime) < 0) ? "MASK" : "MODULO"));<br>    }<br>  }<br>  static long modulo () {<br>    long count = 0;<br>    for (int i = 0; i < 2_000_000_000; i++) {<br>      if ((i % 2) == 0)<br>        count++;<br>    }<br>    return count;<br>  }<br>  static long mask() {<br>    long count = 0;<br>    for (int i = 0; i < 2_000_000_000; i++) {<br>      if ((i & 1) == 0)<br>        count++;<br>    }<br>    return count;<br>  }</div></div><br></blockquote></div></div></div></blockquote></div>