When escape analysis
is turned on, GC still occurs once every millisecond, and the running time is the same as the time without this optimization.
I reached this conclusion by using JMH to test, below is my code and test result.
Code:
/**
* @author Jmc
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 3, time = 10)
@Measurement(iterations = 3, time = 10)
@Fork(1)
public class EscapeAnalysisTest {
/**
* VM Options: -Xlog:gc:empty.gc.log -Xmx30M
*/
@Benchmark
public void empty() {
// do nothing
}
/**
* VM Options: -Xlog:gc:withEA.gc.log -Xmx30M
*/
@Benchmark
public void withEA() {
Object o = null;
for (int i = 0; i < 1_000_000_000; i++) {
o = new Object();
}
int hashcode = o.hashCode();
}
/**
* VM Options: -Xlog:gc:withoutEA.gc.log -Xmx30M -XX:-DoEscapeAnalysis
*/
@Benchmark
public void withoutEA() {
Object o = null;
for (int i = 0; i < 1_000_000_000; i++) {
o = new Object();
}
int hashcode = o.hashCode();
}
}
Output:
- empty - JMH
# JMH version: 1.32
# VM version: JDK 17, Java HotSpot(TM) 64-Bit Server VM, 17+35-LTS-2724
# VM invoker: D:\Programs\JDK\jdk-17\bin\java.exe
# VM options: -Xlog:gc:empty.gc.log -Xmx30M --enable-preview -javaagent:D:\Programs\JetBrains\IntelliJ IDEA 2021.2.2\lib\idea_rt.jar=54629:D:\Programs\JetBrains\IntelliJ IDEA 2021.2.2\bin -Dfile.encoding=UTF-8
# Blackhole mode: full + dont-inline hint
# Warmup: 3 iterations, 10 s each
# Measurement: 3 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: com.test.jmh.EscapeAnalysisTest.empty
...
Benchmark Mode Cnt Score Error Units
EscapeAnalysisTest.empty avgt 3 0.517 ± 1.005 ns/op
- withEA - JMH
# JMH version: 1.32
# VM version: JDK 17, Java HotSpot(TM) 64-Bit Server VM, 17+35-LTS-2724
# VM invoker: D:\Programs\JDK\jdk-17\bin\java.exe
# VM options: -Xlog:gc:withEA.gc.log -Xmx30M --enable-preview -javaagent:D:\Programs\JetBrains\IntelliJ IDEA 2021.2.2\lib\idea_rt.jar=54648:D:\Programs\JetBrains\IntelliJ IDEA 2021.2.2\bin -Dfile.encoding=UTF-8
# Blackhole mode: full + dont-inline hint
# Warmup: 3 iterations, 10 s each
# Measurement: 3 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: com.test.jmh.EscapeAnalysisTest.withEA
...
Benchmark Mode Cnt Score Error Units
EscapeAnalysisTest.withEA avgt 3 900223198.990 ± 468305893.304 ns/op
- withoutEA - JMH
# JMH version: 1.32
# VM version: JDK 17, Java HotSpot(TM) 64-Bit Server VM, 17+35-LTS-2724
# VM invoker: D:\Programs\JDK\jdk-17\bin\java.exe
# VM options: -Xlog:gc:withoutEA.gc.log -Xmx30M -XX:-DoEscapeAnalysis --enable-preview -javaagent:D:\Programs\JetBrains\IntelliJ IDEA 2021.2.2\lib\idea_rt.jar=54708:D:\Programs\JetBrains\IntelliJ IDEA 2021.2.2\bin -Dfile.encoding=UTF-8
# Blackhole mode: full + dont-inline hint
# Warmup: 3 iterations, 10 s each
# Measurement: 3 iterations, 10 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: com.test.jmh.EscapeAnalysisTest.withoutEA
...
Benchmark Mode Cnt Score Error Units
EscapeAnalysisTest.withoutEA avgt 3 905957459.624 ± 472436917.469 ns/op
- empty GC log
[0.039s][info][gc] Using G1
[0.010s][info][gc] Using G1
- withEA GC log
[0.011s][info][gc] Using G1
[0.011s][info][gc] Using G1
[0.596s][info][gc] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 13M->2M(30M) 5.488ms
[0.603s][info][gc] GC(1) Pause Young (Normal) (G1 Evacuation Pause) 14M->2M(30M) 3.900ms
[0.606s][info][gc] GC(2) Pause Young (Normal) (G1 Evacuation Pause) 15M->2M(30M) 0.403ms
...
[63.402s][info][gc] GC(14235) Pause Young (Normal) (G1 Evacuation Pause) 20M->2M(30M) 0.519ms
[63.406s][info][gc] GC(14236) Pause Young (Normal) (G1 Evacuation Pause) 20M->2M(30M) 0.558ms
[63.410s][info][gc] GC(14237) Pause Young (Normal) (G1 Evacuation Pause) 20M->2M(30M) 0.509ms
[63.414s][info][gc] GC(14238) Pause Young (Normal) (G1 Evacuation Pause) 20M->2M(30M) 0.650ms
[63.418s][info][gc] GC(14239) Pause Young (Normal) (G1 Evacuation Pause) 20M->2M(30M) 0.832ms
- withoutEA GC log
[0.013s][info][gc] Using G1
[0.012s][info][gc] Using G1
[0.607s][info][gc] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 13M->2M(30M) 4.942ms
[0.614s][info][gc] GC(1) Pause Young (Normal) (G1 Evacuation Pause) 14M->2M(30M) 3.855ms
[0.617s][info][gc] GC(2) Pause Young (Normal) (G1 Evacuation Pause) 15M->2M(30M) 0.345ms
...
[63.837s][info][gc] GC(15086) Pause Young (Normal) (G1 Evacuation Pause) 20M->2M(30M) 0.971ms
[63.841s][info][gc] GC(15087) Pause Young (Normal) (G1 Evacuation Pause) 20M->2M(30M) 1.038ms
[63.845s][info][gc] GC(15088) Pause Young (Normal) (G1 Evacuation Pause) 20M->2M(30M) 0.953ms
[63.850s][info][gc] GC(15089) Pause Young (Normal) (G1 Evacuation Pause) 20M->2M(30M) 1.233ms
[63.858s][info][gc] GC(15090) Pause Young (Normal) (G1 Evacuation Pause) 20M->2M(30M) 0.499ms
Note: From the code and result above, you can see the empty method doesn't occurs gc and in terms of other two java method, the running time is about the same. The GC still occurs when opened EA
, I want to know the reason.