E Cheung
E Cheung

Reputation: 63

How is the modulo operator implemented in the HotSpot JVM?

I understand that the modulus operation can be optimised using a little & wise magic where the divisor is a power of 2...

Upvotes: 2

Views: 2270

Answers (3)

Joseph Lust
Joseph Lust

Reputation: 19985

I spent some time on this very question, writing this blog post with all the details.

In short:

  • The HotSpot JDK 1.8 irem (mod int) is ~20% slower than the n & (pow2-1) trick
  • The HotSpot JDK 1.8 frem (mod float) is 3x slower
  • You mileage varies based on JIT passes, so the benefit for Int's is minimal

So, there is a clear benefit to not do mod on Doubles, and you might get some benefit with Natural Integer Dividends and power of 2 Divisors.

Upvotes: 3

Durandal
Durandal

Reputation: 20059

Yes, a modulo x % pow(2, n) can be achieved using x & ((1 << n) - 1)

But the %-operator in java can give different results if x is negative, so blindly substituting one for the other can break code.

When bit-addressing, masking etc. the &-variant is commonly used, as its semantically closer to what is used in assembler/C and signedness is usually not wanted/cared about in that case.

As for if the JIT optimizes % to &, the answer is: it depends entirely on the JIT - and thats a moving target.

In case x % y where y isn't a constant its pretty difficult to detect if y is a power of 2, so presumably that case isn't optimizable because detecting it is very difficult or impossible. If y is a constant, the JIT still has prove that x isn't negative - or insert a conditional similar to result = x < 0 ? x % y : x & (y-1). It may or may not do so, depending on JIT in question and also depending on the platform. At least Hotspot is known to use different optimizations for different processors (of the same ISA, namely AMD vs Intel) in some cases.

Upvotes: 2

Ankur Anand
Ankur Anand

Reputation: 3904

Here is one sample code snippet

public class Test {

    public static void main(String[] args)  {
        int a=103;
        int b=5;
        int c=a%b;
        }
    }

Now if you see the compiled code of it You will see

public static void main(java.lang.String[]);
   flags: ACC_PUBLIC, ACC_STATIC
   Code:
     stack=2, locals=4, args_size=1
        0: bipush        103
        2: istore_1
        3: iconst_5
        4: istore_2
        5: iload_1
        6: iload_2
        7: irem
        8: istore_3
        9: return

bipush- push a byte onto the stack as an integer value ie 103

istore_1-Pops an int off the stack and stores it in local variable,in the current frame.

and in 3: iconst_5 constant integer is pushed onto the stack

istore_2 does the same as istore_1 just variable named changed.

Then 5: iload_1 and 6:iload_2 both the variables are again pushed onto stack for operations

now at 7:irem the remainder operator works which you are calling as modulo.

Now how does Remainder operators works. It's Pops two ints(value of a and b) off the operand stack, divides a by b , computes the remainder and pushes the int remainder back onto the stack. The remainder is (b - ((a / b) * b)). This is what is used by the % operator in Java.

Upvotes: 0

Related Questions