<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><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 data-mce-bogus="1"></div><div>regards,<br data-mce-bogus="1"></div><div>Rémi<br data-mce-bogus="1"></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>"Scott Palmer" <swpalmer@gmail.com><br><b>To: </b>"hotspot-dev" <hotspot-dev@openjdk.org><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 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 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></body></html>