1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.util.ArrayList; 25 import java.util.HashMap; 26 import java.util.Map; 27 import java.util.TreeMap; 28 29 final class ThreadUtils { 30 public static void sleep(long durationMS) { 31 try { 32 Thread.sleep(durationMS); 33 } catch (Exception e) { 34 } 35 } 36 } 37 38 class Exitable { 39 private volatile boolean shouldExit = false; 40 41 protected boolean shouldExit() { 42 return shouldExit; 43 } 44 45 public void exit() { 46 shouldExit = true; 47 } 48 } 49 50 class ShortLivedAllocationTask extends Exitable implements Runnable { 51 private Map<String, String> map = new HashMap<>(); 52 53 @Override 54 public void run() { 55 map = new HashMap<>(); 56 while (!shouldExit()) { 57 for (int i = 0; i < 200; i++) { 58 String key = "short" + " key = " + i; 59 String value = "the value is " + i; 60 map.put(key, value); 61 } 62 } 63 } 64 } 65 66 class LongLivedAllocationTask extends Exitable implements Runnable { 67 private Map<String, String> map; 68 69 LongLivedAllocationTask(Map<String, String> map) { 70 this.map = map; 71 } 72 73 @Override 74 public void run() { 75 while (!shouldExit()) { 76 String prefix = "long" + System.currentTimeMillis(); 77 for (int i = 0; i < 10; i++) { 78 String key = prefix + " key = " + i; 79 String value = "the value is " + i; 80 map.put(key, value); 81 } 82 } 83 } 84 } 85 86 class SystemGCTask extends Exitable implements Runnable { 87 private long delayMS; 88 89 SystemGCTask(long delayMS) { 90 this.delayMS = delayMS; 91 } 92 93 @Override 94 public void run() { 95 while (!shouldExit()) { 96 System.gc(); 97 ThreadUtils.sleep(delayMS); 98 } 99 } 100 } 101 102 public class TestSystemGC { 103 private static final int numGroups = 7; 104 private static final int numGCsPerGroup = 4; 105 106 private static Map<String, String> longLivedMap = new TreeMap<>(); 107 108 private static void populateLongLived() { 109 for (int i = 0; i < 1000000; i++) { 110 String key = "all" + " key = " + i; 111 String value = "the value is " + i; 112 longLivedMap.put(key, value); 113 } 114 } 115 116 private static long getDelayMS(int group) { 117 if (group == 0) { 118 return 0; 119 } 120 121 int res = 16; 122 for (int i = 0; i < group; i++) { 123 res *= 2; 124 } 125 return res; 126 } 127 128 private static void doSystemGCs() { 129 ThreadUtils.sleep(1000); 130 131 for (int i = 0; i < numGroups; i++) { 132 for (int j = 0; j < numGCsPerGroup; j++) { 133 System.gc(); 134 ThreadUtils.sleep(getDelayMS(i)); 135 } 136 } 137 } 138 139 private static SystemGCTask createSystemGCTask(int group) { 140 long delay0 = getDelayMS(group); 141 long delay1 = getDelayMS(group + 1); 142 long delay = delay0 + (delay1 - delay0) / 2; 143 return new SystemGCTask(delay); 144 } 145 146 private static void startTask(Runnable task) { 147 if (task != null) { 148 new Thread(task).start(); 149 } 150 } 151 152 private static void exitTask(Exitable task) { 153 if (task != null) { 154 task.exit(); 155 } 156 } 157 158 private static void runAllPhases() { 159 for (int i = 0; i < 4; i++) { 160 SystemGCTask gcTask = 161 (i % 2 == 1) ? createSystemGCTask(numGroups / 3) : null; 162 ShortLivedAllocationTask shortTask = 163 (i == 1 || i == 3) ? new ShortLivedAllocationTask() : null; 164 LongLivedAllocationTask longTask = 165 (i == 2 || i == 3) ? new LongLivedAllocationTask(longLivedMap) : null; 166 167 startTask(gcTask); 168 startTask(shortTask); 169 startTask(longTask); 170 171 doSystemGCs(); 172 173 exitTask(gcTask); 174 exitTask(shortTask); 175 exitTask(longTask); 176 177 ThreadUtils.sleep(1000); 178 } 179 } 180 181 public static void main(String[] args) { 182 populateLongLived(); 183 runAllPhases(); 184 runAllPhases(); 185 } 186 }