While playing with jmh I came across a weird thing I cannot explain.
@BenchmarkMode(Mode.SingleShotTime)
@Measurement(iterations = 10, batchSize = Integer.MAX_VALUE)
@Warmup(iterations = 5, batchSize = Integer.MAX_VALUE)
@State(Scope.Thread)
public class Tests {
private int value;
@Setup(Level.Iteration)
public void setUp() {
value = 1230;
}
@Benchmark
public boolean testConstModN() {
return 12345 % value == 0;
}
@Benchmark
public boolean testNModConst() {
return value % 12345 == 0;
}
}
The results are below
Benchmark Mode Cnt Score Error Units
Tests.testConstModN ss 10 10.789 ± 0.305 s/op
Tests.testNModConst ss 10 7.550 ± 0.067 s/op
I am running on JDK 1.8.0_101, VM 25.101-b13, Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz (family: 0x6, model: 0x3c, stepping: 0x3)
If I set the const equal to the value or if I set the value to 0xffffffff
, nothing changes.
value
to 12345 and use 1230 as your constant? – Appetizingconst
andvalue
are. – Emulous-prof perfasm
to dump the actual assembly generated for the two functions. I suspect thattestNModConst
has been optimized to replace the division with a multiplication. – Constructivismvalue
is the same every time, and the JVM may notice this and opportunistically do aif (value == 12345) return the_answer
as the first operation, or something like that. That doc suggests techniques to avoid this. (IDK, I haven't used JMH, I'm seeing this question because of the x86-64 tag. If you can show the actual JIT-compiled asm that runs for each version, I can tell you how many cycles it should take on your Haswell CPU.) – Gigantic