Вопрос был задан другим членом SO, но был разочарован. В комментариях говорилось, что измерения ошибочны и не имеют смысла.
Однако я смог воспроизвести оригинальную проблему с небольшим эталоном в JMH:
package bench;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.*;
import org.openjdk.jmh.runner.options.*;
import java.util.concurrent.*;
@State(Scope.Benchmark)
public class LoopInc {
private int getValue() {
return ThreadLocalRandom.current().nextInt(2);
}
@Benchmark
public int directInc() {
int result = 0;
for (int i = 0; i < 1000; i++) {
switch (getValue()) {
case 0:
break;
case 1:
result++;
break;
}
}
return result;
}
@Benchmark
public int indirectInc() {
int result = 0;
for (int i = 0; i < 1000; i++) {
boolean incr = false;
switch (getValue()) {
case 0:
break;
case 1:
incr = true;
break;
}
if (incr) {
result++;
}
}
return result;
}
public static void main(String[] args) throws RunnerException {
Options options = new OptionsBuilder()
.include("bench.LoopInc.*")
.warmupIterations(5)
.measurementIterations(10)
.forks(3)
.timeUnit(TimeUnit.MILLISECONDS)
.build();
new Runner(options).run();
}
}
Тесты показывают, что indirectInc
работает в 3 раза быстрее, хотя "оптимизация" вообще не очевидна. Можно предположить, что indirectInc
должен работать немного медленнее, поскольку он включает дополнительную промежуточную операцию.
Benchmark Mode Cnt Score Error Units
LoopInc.directInc thrpt 30 127,301 ± 0,202 ops/ms
LoopInc.indirectInc thrpt 30 378,147 ± 1,144 ops/ms
java version "1.8.0_51"
Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode)
Что заставляет JIT компилировать indirectInc
лучше, чем аналогичный directInc
?