Unexpected performance of operator % vs &
Scott Palmer
swpalmer at gmail.com
Sat Jul 22 22:32:37 UTC 2023
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.
I tested with JMH on two machines and got very different results..
To summarize:
macOS Intel i7 JDK 20.0.1 mask: 1.082 ops/s modulo: 1.080 ops/s
macOS Intel i7 JDK 17.0.7 mask: 1.040 ops/s modulo: 0.815 ops/s
Linux Intel i5 JDK 20.0.1 mask: 0.759 ops/s modulo: 1.070 ops/s
Linux Intel i5 JDK 17.0.8 mask: 0.738 ops/s modulo: 1.039 ops/s
macOS:
CPU: Quad-Core Intel Core i7-7700K
OpenJDK 64-Bit Server VM Zulu17.42+19-CA (build 17.0.7+7-LTS, mixed mode,
sharing)
OpenJDK 64-Bit Server VM Zulu20.30+11-CA (build 20.0.1+9, mixed mode,
sharing)
Linux:
CPU: 12th Gen Intel® Core™ i5-1245U × 12
OpenJDK 64-Bit Server VM Corretto-17.0.8.7.1 (build 17.0.8+7-LTS, mixed
mode, sharing)
OpenJDK 64-Bit Server VM Temurin-20.0.1+9 (build 20.0.1+9, mixed mode,
sharing)
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.
Regards,
Scott
On Sat, Jul 22, 2023 at 11:24 AM Remi Forax <forax at univ-mlv.fr> wrote:
> 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.
>
> regards,
> Rémi
>
> ------------------------------
>
> *From: *"Scott Palmer" <swpalmer at gmail.com>
> *To: *"hotspot-dev" <hotspot-dev at openjdk.org>
> *Sent: *Saturday, July 22, 2023 5:15:48 PM
> *Subject: *Unexpected performance of operator % vs &
>
> I hope this is the appropriate list for this question.
>
> Given the following Java code to test if a number is even or odd I
> observed unexpected results.
>
> boolean evenA = ((i % 2) == 0);
>
> boolean evenB = ((i & 1) == 0);
>
> 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.
> 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.
>
> 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.
>
> 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.
>
> Am I making a mistake here (other than assuming what is faster before
> profiling)?
> Is this something that could be improved/fixed in the compiler?
>
> Regards,
>
> Scott
>
> My simple experiment:
>
> public static void main(String [] args) {
> for (int i = 0; i < 10; i++) {
> long start = System.nanoTime();
> long maskCount = mask();
> var maskTime = Duration.ofNanos(System.nanoTime()-start);
> System.out.printf("%d mask method took: %s%n", maskCount,
> maskTime);
> start = System.nanoTime();
> long moduloCount = modulo();
> var moduloTime = Duration.ofNanos(System.nanoTime()-start);
> System.out.printf("%d modulo method took: %s%n", moduloCount,
> moduloTime);
> System.out.println("fastest: " + ((maskTime.compareTo(moduloTime) <
> 0) ? "MASK" : "MODULO"));
> }
> }
> static long modulo () {
> long count = 0;
> for (int i = 0; i < 2_000_000_000; i++) {
> if ((i % 2) == 0)
> count++;
> }
> return count;
> }
> static long mask() {
> long count = 0;
> for (int i = 0; i < 2_000_000_000; i++) {
> if ((i & 1) == 0)
> count++;
> }
> return count;
> }
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/hotspot-dev/attachments/20230722/912690a4/attachment.htm>
More information about the hotspot-dev
mailing list