How is the modulo operator implemented in the HotSpot JVM?

孤街浪徒 提交于 2019-12-02 03:34:43

问题


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

  • and presumably this an optimisation that the JIT compiler makes?

回答1:


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.




回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/29844345/how-is-the-modulo-operator-implemented-in-the-hotspot-jvm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!