1 package nsu.fit.javaperf; 2 3 import java.io.Console; 4 import java.io.PrintWriter; 5 import java.io.StringReader; 6 import java.lang.management.ManagementFactory; 7 import java.lang.management.RuntimeMXBean; 8 import java.util.ArrayList; 9 import java.util.LinkedList; 10 import java.util.List; 11 import java.util.Scanner; 12 import java.util.concurrent.atomic.AtomicLong; 13 14 /** 15 * JVM load-set tests 16 */ 17 public class LoadSet { 18 19 static final Object rlock = new Object(); 20 21 static List<Task> tasks = new ArrayList<>(); //Tasks for runner 22 23 static GarbageProducer garbageProducer; 24 25 26 static class Garbage { 27 private List list = new LinkedList(); 28 29 Garbage() { 30 for (int i = 0; i < 5; i++) { 31 list.add(new byte[1]); 32 } 33 } 34 } 35 36 static class GarbageProducer extends Thread { 37 38 private List<Garbage> garbageStorage; 39 40 AtomicLong garbageRemovePeriod = new AtomicLong(150); 41 42 AtomicLong garbageAmount = new AtomicLong(50000); 43 44 private volatile boolean stopped; 45 46 GarbageProducer() { 47 super("GarbageProducer"); 48 } 49 50 public void run() { 51 garbageStorage = new ArrayList<>(); 52 try { 53 // период удаления созданного мусора 54 long lastGarbageRemoveTime = System.currentTimeMillis(); 55 56 // количество мусора, создаваемого за одну итерацию 57 while (!stopped) { 58 for (int i = 0; i < garbageAmount.longValue(); i++) { 59 garbageStorage.add(new Garbage()); 60 } 61 if (System.currentTimeMillis() > (lastGarbageRemoveTime + garbageRemovePeriod.longValue())) { 62 garbageStorage.clear(); 63 Thread.sleep(100); 64 lastGarbageRemoveTime = System.currentTimeMillis(); 65 } 66 } 67 garbageStorage.clear(); 68 garbageStorage = null; 69 70 } catch (InterruptedException e) { 71 e.printStackTrace(); 72 } 73 } 74 75 public void stopGarbageProducer() { 76 stopped = true; 77 } 78 } 79 80 81 static class Task { 82 final String name; 83 final String cmdline; 84 85 Task(String name) { 86 this.name = name; 87 this.cmdline = name; 88 } 89 90 Task(String name, String cmdline) { 91 this.name = name; 92 this.cmdline = cmdline; 93 } 94 95 public String toString() { 96 final StringBuilder sb = new StringBuilder("Task{"); 97 sb.append("name='").append(name).append('\''); 98 sb.append(", cmdline='").append(cmdline).append('\''); 99 sb.append('}'); 100 return sb.toString(); 101 } 102 } 103 104 static class TaskRunner implements Runnable { 105 106 TaskRunner() { 107 } 108 109 void clear() { 110 System.err.printf("[%s]: Clearing all allocated memory\n", Thread.currentThread().getName()); 111 garbageProducer.stopGarbageProducer(); 112 } 113 114 static void yg(String cmd) { 115 Scanner s = new Scanner(new StringReader(cmd)); 116 String t = s.next(); 117 long amount = 0; 118 if (s.hasNextLong()) { 119 amount = s.nextLong(); 120 } 121 long rperiod = 0; 122 if (s.hasNextLong()) { 123 rperiod = s.nextLong(); 124 } 125 if (rperiod > 0) { 126 garbageProducer.garbageRemovePeriod.set(rperiod); 127 } 128 if (amount > 0) { 129 garbageProducer.garbageAmount.set(amount); 130 } 131 if (garbageProducer == null || !garbageProducer.isAlive()) { 132 garbageProducer = new GarbageProducer(); 133 garbageProducer.start(); 134 } 135 System.err.printf("Young garbage generator: amount: %d, rm period: %d\n", 136 garbageProducer.garbageAmount.longValue(), 137 garbageProducer.garbageRemovePeriod.longValue()); 138 } 139 140 public void run() { 141 boolean active = true; 142 while (active) { 143 Task task; 144 synchronized (rlock) { 145 if (tasks.isEmpty()) { 146 try { 147 rlock.wait(); 148 } catch (InterruptedException e) { 149 e.printStackTrace(); 150 continue; 151 } 152 } 153 if (!tasks.isEmpty()) { 154 task = tasks.remove(0); 155 } else { 156 continue; 157 } 158 } 159 String tn = task.name; 160 switch (tn) { 161 case "exit": 162 active = false; 163 break; 164 case "clear": 165 clear(); 166 break; 167 case "yg": 168 yg(task.cmdline); 169 break; 170 case "ygs": 171 System.err.println("Stopping young garbage generator"); 172 garbageProducer.stopGarbageProducer(); 173 break; 174 } 175 } 176 } 177 } 178 179 static void sendTask(Task t) { 180 synchronized (rlock) { 181 tasks.add(t); 182 rlock.notify(); 183 } 184 } 185 186 static void info(Console c, boolean memonly) { 187 PrintWriter w = c.writer(); 188 Runtime rt = Runtime.getRuntime(); 189 w.printf("Max memory: %d (%dMb)\n", rt.maxMemory(), (int) (rt.maxMemory() / (1024 * 1024))); 190 w.printf("Total memory: %d (%dMb)\n", rt.totalMemory(), (int) (rt.totalMemory() / (1024 * 1024))); 191 w.printf("Free memory: %d (%dMb)\n", rt.freeMemory(), (int) (rt.freeMemory() / (1024 * 1024))); 192 193 194 if (!memonly) { 195 RuntimeMXBean rtMx = ManagementFactory.getRuntimeMXBean(); 196 List<String> jargs = rtMx.getInputArguments(); 197 StringBuilder sb = new StringBuilder(); 198 for (int i = 0; i < jargs.size(); ++i) { 199 if (i > 0) { 200 sb.append(", "); 201 } 202 sb.append(jargs.get(i)); 203 } 204 w.printf("[%s] %s %s %s (%s)\n", rtMx.getName(), rtMx.getVmName(), rtMx.getVmVendor(), rtMx.getSpecVersion(), rtMx.getVmVersion()); 205 w.println("JVM args: " + sb); 206 } 207 if (garbageProducer != null) { 208 w.printf("Young garbage generator: %s, amount: %d, rm period: %d\n", 209 garbageProducer.isAlive() ? "ACTIVE" : "NOT ACTIVE", 210 garbageProducer.garbageAmount.longValue(), 211 garbageProducer.garbageRemovePeriod.longValue()); 212 } else { 213 w.printf("Young garbage generator: NOT ACTIVE\n"); 214 } 215 w.flush(); 216 } 217 218 219 static void help(Console c) { 220 PrintWriter w = c.writer(); 221 w.println("\t Available commmands:\n"); 222 w.println("\t?|h|help: Print this help."); 223 w.println("\tq|quit|exit: Exit peogram."); 224 w.println("\ti|info: Show brief system info."); 225 w.println("\tgc: Run GC."); 226 w.println("\tclear: Clear all memory allocated by TaskRunner."); 227 w.println("\tyg [amount] [removeperiod]: Start generate young garbage. By default amount: 50000, removeperiod: 150ms"); 228 w.println("\tyg stop: Stop young garbage generator"); 229 w.flush(); 230 } 231 232 public static void main(String[] args) throws Exception { 233 Console c = System.console(); 234 if (c == null) { 235 System.err.println("Java program cannot open interactive console"); 236 System.exit(1); 237 } 238 239 Thread tf = new Thread(new TaskRunner()); 240 tf.setName("TaskThread"); 241 tf.start(); 242 243 PrintWriter w = c.writer(); 244 w.println("Welcome to JVM load set."); 245 String cmd; 246 while ((cmd = c.readLine("> ")) != null) { 247 cmd = cmd.trim(); 248 switch (cmd) { 249 case "?": 250 case "h": 251 case "help": 252 help(c); 253 break; 254 case "q": 255 case "quit": 256 case "exit": 257 if (garbageProducer != null && garbageProducer.isAlive()) { 258 garbageProducer.stopGarbageProducer(); 259 garbageProducer.join(1000); 260 } 261 sendTask(new Task("exit")); 262 tf.join(1000); 263 System.exit(0); 264 break; 265 case "i": 266 case "info": 267 info(c, false); 268 break; 269 case "gc": 270 w.println("Before GC:"); 271 info(c, true); 272 for (int i = 0; i < 2; ++i) { 273 Runtime.getRuntime().gc(); 274 Thread.sleep(100); 275 } 276 w.println("After GC:"); 277 info(c, true); 278 break; 279 case "clear": 280 sendTask(new Task(cmd)); 281 break; 282 default: 283 if (cmd.startsWith("yg")) { 284 if (cmd.matches("yg\\s+stop")) { 285 sendTask(new Task("ygs", cmd)); 286 } else { 287 sendTask(new Task("yg", cmd)); 288 } 289 } 290 break; 291 292 } 293 } 294 } 295 } 296