8225084: gc/z/TestHighUsage.java fails with unexpected allocation stall
authorpliden
Wed, 05 Jun 2019 10:43:45 +0200
changeset 55224 1de459182903
parent 55223 3f8a81f5d1b2
child 55225 ae3ef834deed
8225084: gc/z/TestHighUsage.java fails with unexpected allocation stall Reviewed-by: eosterlund
test/hotspot/jtreg/gc/z/TestHighUsage.java
--- a/test/hotspot/jtreg/gc/z/TestHighUsage.java	Wed Jun 05 10:43:45 2019 +0200
+++ b/test/hotspot/jtreg/gc/z/TestHighUsage.java	Wed Jun 05 10:43:45 2019 +0200
@@ -38,18 +38,21 @@
     static class Test {
         private static final int K = 1024;
         private static final int M = K * K;
-        private static final long startAt = 16 * M;
-        private static final long spikeAt = 4 * M;
+        private static final long maxCapacity = Runtime.getRuntime().maxMemory();
+        private static final long slowAllocationThreshold = 16 * M;
+        private static final long highUsageThreshold = maxCapacity / 20; // 5%
         private static volatile LinkedList<byte[]> keepAlive;
         private static volatile Object dummy;
 
         public static void main(String[] args) throws Exception {
+            System.out.println("Max capacity: " + (maxCapacity / M) + "M");
+            System.out.println("High usage threshold: " + (highUsageThreshold / M) + "M");
             System.out.println("Allocating live-set");
 
             // Allocate live-set
             keepAlive = new LinkedList<>();
-            while (Runtime.getRuntime().freeMemory() > startAt) {
-                while (Runtime.getRuntime().freeMemory() > startAt) {
+            while (Runtime.getRuntime().freeMemory() > slowAllocationThreshold) {
+                while (Runtime.getRuntime().freeMemory() > slowAllocationThreshold) {
                     keepAlive.add(new byte[128 * K]);
                 }
 
@@ -60,21 +63,18 @@
 
             System.out.println("Allocating garbage slowly");
 
-            // Allocate garbage slowly, such that the sampled allocation rate on
-            // average becomes zero MB/s for the last 1 second windows. If free
-            // memory goes below the spike limit we induce an allocation spike.
-            // The expected behavior is that the "High Usage" rule kicks in before
-            // the spike happens, avoiding an "Allocation Stall".
+            // Allocate garbage slowly, so that the sampled allocation rate on average
+            // becomes zero MB/s for the last 1 second windows. Once we reach the high
+            // usage threshold we idle to allow for a "High Usage" GC cycle to happen.
+            // We need to allocate slowly to avoid an "Allocation Rate" GC cycle.
             for (int i = 0; i < 300; i++) {
-                final long free = Runtime.getRuntime().freeMemory();
-                System.out.println("Free: " + (free / M) + "M");
-
-                if (free > spikeAt) {
-                    // Low allocation rate
+                if (Runtime.getRuntime().freeMemory() > highUsageThreshold) {
+                    // Allocate
                     dummy = new byte[128 * K];
+                    System.out.println("Free: " + (Runtime.getRuntime().freeMemory() / M) + "M (Allocating)");
                 } else {
-                    // High allocation rate
-                    dummy = new byte[8 * M];
+                    // Idle
+                    System.out.println("Free: " + (Runtime.getRuntime().freeMemory() / M) + "M (Idling)");
                 }
 
                 Thread.sleep(250);
@@ -93,7 +93,7 @@
                                                   "-Xmx128M",
                                                   "-XX:ParallelGCThreads=1",
                                                   "-XX:ConcGCThreads=1",
-                                                  "-Xlog:gc",
+                                                  "-Xlog:gc,gc+start",
                                                   Test.class.getName() })
                     .shouldNotContain("Allocation Stall")
                     .shouldContain("High Usage")