1 /* 2 * Copyright (c) 2016, 2018, 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 /* 25 * @test TestStressIHOPMultiThread 26 * @bug 8148397 27 * @key stress 28 * @summary Stress test for IHOP 29 * @requires vm.gc.G1 30 * @run main/othervm/timeout=200 -Xmx128m -XX:G1HeapWastePercent=0 -XX:G1MixedGCCountTarget=1 31 * -XX:+UseG1GC -XX:G1HeapRegionSize=1m -XX:+G1UseAdaptiveIHOP 32 * -Xlog:gc+ihop=debug,gc+ihop+ergo=debug,gc+ergo=debug:TestStressIHOPMultiThread1.log 33 * -Dtimeout=2 -DheapUsageMinBound=30 -DheapUsageMaxBound=80 34 * -Dthreads=2 TestStressIHOPMultiThread 35 * @run main/othervm/timeout=200 -Xmx256m -XX:G1HeapWastePercent=0 -XX:G1MixedGCCountTarget=1 36 * -XX:+UseG1GC -XX:G1HeapRegionSize=2m -XX:+G1UseAdaptiveIHOP 37 * -Xlog:gc+ihop=debug,gc+ihop+ergo=debug,gc+ergo=debug:TestStressIHOPMultiThread2.log 38 * -Dtimeout=2 -DheapUsageMinBound=60 -DheapUsageMaxBound=90 39 * -Dthreads=3 TestStressIHOPMultiThread 40 * @run main/othervm/timeout=200 -Xmx256m -XX:G1HeapWastePercent=0 -XX:G1MixedGCCountTarget=1 41 * -XX:+UseG1GC -XX:G1HeapRegionSize=4m -XX:-G1UseAdaptiveIHOP 42 * -Xlog:gc+ihop=debug,gc+ihop+ergo=debug,gc+ergo=debug:TestStressIHOPMultiThread3.log 43 * -Dtimeout=2 -DheapUsageMinBound=40 -DheapUsageMaxBound=90 44 * -Dthreads=5 TestStressIHOPMultiThread 45 * @run main/othervm/timeout=200 -Xmx128m -XX:G1HeapWastePercent=0 -XX:G1MixedGCCountTarget=1 46 * -XX:+UseG1GC -XX:G1HeapRegionSize=8m -XX:+G1UseAdaptiveIHOP 47 * -Xlog:gc+ihop=debug,gc+ihop+ergo=debug,gc+ergo=debug:TestStressIHOPMultiThread4.log 48 * -Dtimeout=2 -DheapUsageMinBound=20 -DheapUsageMaxBound=90 49 * -Dthreads=10 TestStressIHOPMultiThread 50 * @run main/othervm/timeout=200 -Xmx512m -XX:G1HeapWastePercent=0 -XX:G1MixedGCCountTarget=1 51 * -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:+G1UseAdaptiveIHOP 52 * -Xlog:gc+ihop=debug,gc+ihop+ergo=debug,gc+ergo=debug:TestStressIHOPMultiThread5.log 53 * -Dtimeout=2 -DheapUsageMinBound=20 -DheapUsageMaxBound=90 54 * -Dthreads=17 TestStressIHOPMultiThread 55 */ 56 57 import java.util.ArrayList; 58 import java.util.LinkedList; 59 import java.util.List; 60 61 /** 62 * Stress test for Adaptive IHOP. Starts a number of threads that fill and free 63 * specified amount of memory. Tests work with enabled IHOP logging. 64 * 65 */ 66 public class TestStressIHOPMultiThread { 67 68 public final static List<Object> GARBAGE = new LinkedList<>(); 69 70 private final long HEAP_SIZE; 71 // Amount of memory to be allocated before iterations start 72 private final long HEAP_PREALLOC_SIZE; 73 // Amount of memory to be allocated and freed during iterations 74 private final long HEAP_ALLOC_SIZE; 75 private final int CHUNK_SIZE = 100000; 76 77 private final int TIMEOUT; 78 private final int THREADS; 79 private final int HEAP_LOW_BOUND; 80 private final int HEAP_HIGH_BOUND; 81 82 private volatile boolean running = true; 83 private final List<AllocationThread> threads; 84 85 public static void main(String[] args) throws InterruptedException { 86 new TestStressIHOPMultiThread().start(); 87 88 } 89 90 TestStressIHOPMultiThread() { 91 92 TIMEOUT = Integer.getInteger("timeout") * 60; 93 THREADS = Integer.getInteger("threads"); 94 HEAP_LOW_BOUND = Integer.getInteger("heapUsageMinBound"); 95 HEAP_HIGH_BOUND = Integer.getInteger("heapUsageMaxBound"); 96 HEAP_SIZE = Runtime.getRuntime().maxMemory(); 97 98 HEAP_PREALLOC_SIZE = HEAP_SIZE * HEAP_LOW_BOUND / 100; 99 HEAP_ALLOC_SIZE = HEAP_SIZE * (HEAP_HIGH_BOUND - HEAP_LOW_BOUND) / 100; 100 101 threads = new ArrayList<>(THREADS); 102 } 103 104 public void start() throws InterruptedException { 105 fill(); 106 createThreads(); 107 waitForStress(); 108 stressDone(); 109 waitForFinish(); 110 } 111 112 /** 113 * Fills HEAP_PREALLOC_SIZE bytes of garbage. 114 */ 115 private void fill() { 116 long allocated = 0; 117 while (allocated < HEAP_PREALLOC_SIZE) { 118 GARBAGE.add(new byte[CHUNK_SIZE]); 119 allocated += CHUNK_SIZE; 120 } 121 } 122 123 /** 124 * Creates a number of threads which will fill and free amount of memory. 125 */ 126 private void createThreads() { 127 for (int i = 0; i < THREADS; ++i) { 128 System.out.println("Create thread " + i); 129 AllocationThread thread =new TestStressIHOPMultiThread.AllocationThread(i, HEAP_ALLOC_SIZE / THREADS); 130 // Put reference to thread garbage into common garbage for avoiding possible optimization. 131 GARBAGE.add(thread.getList()); 132 threads.add(thread); 133 } 134 threads.forEach(t -> t.start()); 135 } 136 137 /** 138 * Wait each thread for finishing 139 */ 140 private void waitForFinish() { 141 threads.forEach(thread -> { 142 thread.silentJoin(); 143 }); 144 } 145 146 private boolean isRunning() { 147 return running; 148 } 149 150 private void stressDone() { 151 running = false; 152 } 153 154 private void waitForStress() throws InterruptedException { 155 Thread.sleep(TIMEOUT * 1000); 156 } 157 158 private class AllocationThread extends Thread { 159 160 private final List<Object> garbage; 161 162 private final long amountOfGarbage; 163 private final int threadId; 164 165 public AllocationThread(int id, long amount) { 166 super("Thread " + id); 167 threadId = id; 168 amountOfGarbage = amount; 169 garbage = new LinkedList<>(); 170 } 171 172 /** 173 * Returns list of garbage. 174 * @return List with thread garbage. 175 */ 176 public List<Object> getList(){ 177 return garbage; 178 } 179 180 @Override 181 public void run() { 182 System.out.println("Start the thread " + threadId); 183 while (TestStressIHOPMultiThread.this.isRunning()) { 184 try { 185 allocate(amountOfGarbage); 186 } catch (OutOfMemoryError e) { 187 free(); 188 System.out.println("OutOfMemoryError occurred in thread " + threadId); 189 break; 190 } 191 free(); 192 } 193 } 194 195 private void silentJoin() { 196 System.out.println("Join the thread " + threadId); 197 try { 198 join(); 199 } catch (InterruptedException ie) { 200 throw new RuntimeException(ie); 201 } 202 } 203 204 /** 205 * Allocates thread local garbage 206 */ 207 private void allocate(long amount) { 208 long allocated = 0; 209 while (allocated < amount && TestStressIHOPMultiThread.this.isRunning()) { 210 garbage.add(new byte[CHUNK_SIZE]); 211 allocated += CHUNK_SIZE; 212 } 213 } 214 215 /** 216 * Frees thread local garbage 217 */ 218 private void free() { 219 garbage.clear(); 220 } 221 } 222 } --- EOF ---