[Java][JVM][Tuning][Profiling][G1][JIT] Why is Arrays.fill 265 times slower on G1GC?
Pangram verdict · v3.3
We believe that this text is a mix of AI and human-written content.
AI likelihood · overall
MixedArticle text · 223 words · 1 segments analyzed
Big fat warning This article shows some JVM tuning using JVM flags. You should never use any JVM flags without knowing what consequences they may produce. Most of the flags used here are diagnostic ones, used to understand what is going on. Only one of them is worth considering on production, and I write about it at the very end. The benchmark It started with a benchmark that I expected to be boring. Fill two arrays with a reference, once on G1GC, once on ParallelGC: package pl.ks.jmh; import org.openjdk.jmh.annotations.*; import java.util.Arrays; import java.util.concurrent.TimeUnit; @State(Scope.Benchmark) public class MyBenchmark { Object[] table = new Object[1024 * 1024]; Object[] table2 = new Object[1024 * 1024]; Object mark = new Object(); @Benchmark @Fork(value = 1, warmups = 1, jvmArgsAppend = "-XX:+UseParallelGC") @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 1) @Measurement(iterations = 2) @BenchmarkMode(Mode.AverageTime) public void parallelGC() { Arrays.fill(table, mark); Arrays.fill(table2, mark); } @Benchmark @Fork(value = 1, warmups = 1, jvmArgsAppend = "-XX:+UseG1GC") @OutputTimeUnit(TimeUnit.MICROSECONDS) @Warmup(iterations = 1) @Measurement(iterations = 2) @BenchmarkMode(Mode.AverageTime) public void g1GC() { Arrays.fill(table, mark); Arrays.fill(table2, mark); } } There is no allocation in these methods, so there are no GC cycles at all during the measurement. Whatever the difference is, it cannot be “G1 collects garbage slower”. And yet: Benchmark Mode Cnt Score Units MyBenchmark.g1GC avgt 2 139019,174 us/op MyBenchmark.parallelGC avgt 2 525,537 us/op 139 milliseconds versus 0.5 millisecond.