It seems that the new Parallel full GC implementation from JDK-8347711 has a significant difference from the previous implementation. A simple reproducer:
```
import java.util.ArrayList;
import java.util.List;
public class GCStressTest {
private static final List<byte[]> tenured = new ArrayList<>();
public static void main(String[] args) {
while (true) {
tenured.clear();
for (int i = 0; i < 100; i++) tenured.add(new byte[1024 * 1024]);
}
}
}
```
Shows that with COH, some full collections are unproductive, and are immediately followed by another full collection (which has maximum compaction enabled, which allows it to be productive).
```
lilliput/java -XX:+UseCompactObjectHeaders -XX:+UseParallelGC -Xms256m -Xmx256m -Xlog:gc GCStressTest.java | grep 'Full'
# Every 6th Full GC is unproductive
# Full GCs always come in back-to-back pairs
[2.163s][info][gc] GC(182) Pause Full (Allocation Failure) 185M->185M(228M) 6.211ms <--- unproductive
[2.179s][info][gc] GC(183) Pause Full (Allocation Failure) 225M->15M(228M) 10.410ms <--- back-to-back (this second one uses maximum compaction)
[2.224s][info][gc] GC(190) Pause Full (Allocation Failure) 180M->31M(228M) 6.251ms
[2.262s][info][gc] GC(191) Pause Full (Allocation Failure) 225M->5M(228M) 8.710ms
[2.313s][info][gc] GC(199) Pause Full (Allocation Failure) 188M->31M(228M) 6.257ms
[2.354s][info][gc] GC(200) Pause Full (Allocation Failure) 225M->23M(228M) 12.525ms
[2.409s][info][gc] GC(209) Pause Full (Allocation Failure) 185M->185M(228M) 6.282ms <--- unproductive
[2.425s][info][gc] GC(210) Pause Full (Allocation Failure) 225M->15M(228M) 10.491ms
...
```
```
# same, but -XX:-UseCompactObjectHeaders
# No unproductive Full GCs
# Full GCs are not back-to-back
[1.827s][info][gc] GC(187) Pause Full (Allocation Failure) 188M->82M(228M) 7.249ms
[1.858s][info][gc] GC(192) Pause Full (Allocation Failure) 193M->22M(228M) 4.416ms
[1.901s][info][gc] GC(199) Pause Full (Allocation Failure) 185M->18M(228M) 4.200ms
[1.962s][info][gc] GC(209) Pause Full (Allocation Failure) 208M->98M(228M) 7.965ms
[1.991s][info][gc] GC(213) Pause Full (Allocation Failure) 196M->110M(228M) 8.272ms
[2.014s][info][gc] GC(216) Pause Full (Allocation Failure) 192M->94M(228M) 7.695ms
[2.043s][info][gc] GC(220) Pause Full (Allocation Failure) 188M->106M(228M) 8.287ms
...
```
My testing indicates that a maximum compaction collection is always productive, but I didn't get any further than that so far.
```
import java.util.ArrayList;
import java.util.List;
public class GCStressTest {
private static final List<byte[]> tenured = new ArrayList<>();
public static void main(String[] args) {
while (true) {
tenured.clear();
for (int i = 0; i < 100; i++) tenured.add(new byte[1024 * 1024]);
}
}
}
```
Shows that with COH, some full collections are unproductive, and are immediately followed by another full collection (which has maximum compaction enabled, which allows it to be productive).
```
lilliput/java -XX:+UseCompactObjectHeaders -XX:+UseParallelGC -Xms256m -Xmx256m -Xlog:gc GCStressTest.java | grep 'Full'
# Every 6th Full GC is unproductive
# Full GCs always come in back-to-back pairs
[2.163s][info][gc] GC(182) Pause Full (Allocation Failure) 185M->185M(228M) 6.211ms <--- unproductive
[2.179s][info][gc] GC(183) Pause Full (Allocation Failure) 225M->15M(228M) 10.410ms <--- back-to-back (this second one uses maximum compaction)
[2.224s][info][gc] GC(190) Pause Full (Allocation Failure) 180M->31M(228M) 6.251ms
[2.262s][info][gc] GC(191) Pause Full (Allocation Failure) 225M->5M(228M) 8.710ms
[2.313s][info][gc] GC(199) Pause Full (Allocation Failure) 188M->31M(228M) 6.257ms
[2.354s][info][gc] GC(200) Pause Full (Allocation Failure) 225M->23M(228M) 12.525ms
[2.409s][info][gc] GC(209) Pause Full (Allocation Failure) 185M->185M(228M) 6.282ms <--- unproductive
[2.425s][info][gc] GC(210) Pause Full (Allocation Failure) 225M->15M(228M) 10.491ms
...
```
```
# same, but -XX:-UseCompactObjectHeaders
# No unproductive Full GCs
# Full GCs are not back-to-back
[1.827s][info][gc] GC(187) Pause Full (Allocation Failure) 188M->82M(228M) 7.249ms
[1.858s][info][gc] GC(192) Pause Full (Allocation Failure) 193M->22M(228M) 4.416ms
[1.901s][info][gc] GC(199) Pause Full (Allocation Failure) 185M->18M(228M) 4.200ms
[1.962s][info][gc] GC(209) Pause Full (Allocation Failure) 208M->98M(228M) 7.965ms
[1.991s][info][gc] GC(213) Pause Full (Allocation Failure) 196M->110M(228M) 8.272ms
[2.014s][info][gc] GC(216) Pause Full (Allocation Failure) 192M->94M(228M) 7.695ms
[2.043s][info][gc] GC(220) Pause Full (Allocation Failure) 188M->106M(228M) 8.287ms
...
```
My testing indicates that a maximum compaction collection is always productive, but I didn't get any further than that so far.
- caused by
-
JDK-8347711 [Lilliput] Parallel GC support for compact identity hashcode
-
- Resolved
-