Mercurial > hg > truffle
annotate test/runtime/NMT/MallocStressTest.java @ 20531:817815bc3502
Merge
author | asaha |
---|---|
date | Mon, 22 Sep 2014 08:24:04 -0700 |
parents | 3f9ff5e261c6 |
children |
rev | line source |
---|---|
20394 | 1 /* |
2 * Copyright (c) 2014, 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 | |
26 * @summary Stress test for malloc tracking | |
20401
3f9ff5e261c6
8055765: Misplaced @key stress prevents MallocSiteHashOverflow.java and MallocStressTest.java tests from running
gtriantafill
parents:
20394
diff
changeset
|
27 * @key nmt jcmd stress |
20394 | 28 * @library /testlibrary /testlibrary/whitebox |
29 * @build MallocStressTest | |
30 * @ignore - This test is disabled since it will stress NMT and timeout during normal testing | |
31 * @run main ClassFileInstaller sun.hotspot.WhiteBox | |
32 * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocStressTest | |
33 */ | |
34 | |
35 import java.util.concurrent.atomic.AtomicInteger; | |
36 import java.util.ArrayList; | |
37 import java.util.List; | |
38 import java.util.Random; | |
39 import com.oracle.java.testlibrary.*; | |
40 import sun.hotspot.WhiteBox; | |
41 | |
42 public class MallocStressTest { | |
43 private static int K = 1024; | |
44 | |
45 // The stress test runs in three phases: | |
46 // 1. alloc: A lot of malloc with fewer free, which simulates a burst memory allocation | |
47 // that is usually seen during startup or class loading. | |
48 // 2. pause: Pause the test to check accuracy of native memory tracking | |
49 // 3. release: Release all malloc'd memory and check native memory tracking result. | |
50 public enum TestPhase { | |
51 alloc, | |
52 pause, | |
53 release | |
54 }; | |
55 | |
56 static TestPhase phase = TestPhase.alloc; | |
57 | |
58 // malloc'd memory | |
59 static ArrayList<MallocMemory> mallocd_memory = new ArrayList<MallocMemory>(); | |
60 static long mallocd_total = 0; | |
61 static WhiteBox whiteBox; | |
62 static AtomicInteger pause_count = new AtomicInteger(); | |
63 | |
64 static boolean is_64_bit_system; | |
65 | |
66 private static boolean is_64_bit_system() { return is_64_bit_system; } | |
67 | |
68 public static void main(String args[]) throws Exception { | |
69 is_64_bit_system = (Platform.is64bit()); | |
70 | |
71 OutputAnalyzer output; | |
72 whiteBox = WhiteBox.getWhiteBox(); | |
73 | |
74 // Grab my own PID | |
75 String pid = Integer.toString(ProcessTools.getProcessId()); | |
76 ProcessBuilder pb = new ProcessBuilder(); | |
77 | |
78 AllocThread[] alloc_threads = new AllocThread[256]; | |
79 ReleaseThread[] release_threads = new ReleaseThread[64]; | |
80 | |
81 int index; | |
82 // Create many allocation threads | |
83 for (index = 0; index < alloc_threads.length; index ++) { | |
84 alloc_threads[index] = new AllocThread(); | |
85 } | |
86 | |
87 // Fewer release threads | |
88 for (index = 0; index < release_threads.length; index ++) { | |
89 release_threads[index] = new ReleaseThread(); | |
90 } | |
91 | |
92 if (is_64_bit_system()) { | |
93 sleep_wait(2*60*1000); | |
94 } else { | |
95 sleep_wait(60*1000); | |
96 } | |
97 // pause the stress test | |
98 phase = TestPhase.pause; | |
99 while (pause_count.intValue() < alloc_threads.length + release_threads.length) { | |
100 sleep_wait(10); | |
101 } | |
102 | |
103 long mallocd_total_in_KB = (mallocd_total + K / 2) / K; | |
104 | |
105 // Now check if the result from NMT matches the total memory allocated. | |
106 String expected_test_summary = "Test (reserved=" + mallocd_total_in_KB +"KB, committed=" + mallocd_total_in_KB + "KB)"; | |
107 // Run 'jcmd <pid> VM.native_memory summary' | |
108 pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); | |
109 output = new OutputAnalyzer(pb.start()); | |
110 output.shouldContain(expected_test_summary); | |
111 | |
112 // Release all allocated memory | |
113 phase = TestPhase.release; | |
114 synchronized(mallocd_memory) { | |
115 mallocd_memory.notifyAll(); | |
116 } | |
117 | |
118 // Join all threads | |
119 for (index = 0; index < alloc_threads.length; index ++) { | |
120 try { | |
121 alloc_threads[index].join(); | |
122 } catch (InterruptedException e) { | |
123 } | |
124 } | |
125 | |
126 for (index = 0; index < release_threads.length; index ++) { | |
127 try { | |
128 release_threads[index].join(); | |
129 } catch (InterruptedException e) { | |
130 } | |
131 } | |
132 | |
133 // All test memory allocated should be released | |
134 output = new OutputAnalyzer(pb.start()); | |
135 output.shouldNotContain("Test (reserved="); | |
136 | |
137 // Verify that tracking level has not been downgraded | |
138 pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "statistics"}); | |
139 output = new OutputAnalyzer(pb.start()); | |
140 output.shouldNotContain("Tracking level has been downgraded due to lack of resources"); | |
141 } | |
142 | |
143 private static void sleep_wait(int n) { | |
144 try { | |
145 Thread.sleep(n); | |
146 } catch (InterruptedException e) { | |
147 } | |
148 } | |
149 | |
150 | |
151 static class MallocMemory { | |
152 private long addr; | |
153 private int size; | |
154 | |
155 MallocMemory(long addr, int size) { | |
156 this.addr = addr; | |
157 this.size = size; | |
158 } | |
159 | |
160 long addr() { return this.addr; } | |
161 int size() { return this.size; } | |
162 } | |
163 | |
164 static class AllocThread extends Thread { | |
165 AllocThread() { | |
166 this.setName("MallocThread"); | |
167 this.start(); | |
168 } | |
169 | |
170 // AllocThread only runs "Alloc" phase | |
171 public void run() { | |
172 Random random = new Random(); | |
173 while (MallocStressTest.phase == TestPhase.alloc) { | |
174 int r = Math.abs(random.nextInt()); | |
175 // Only malloc small amount to avoid OOM | |
176 int size = r % 32; | |
177 if (is_64_bit_system()) { | |
178 r = r % 32 * K; | |
179 } else { | |
180 r = r % 64; | |
181 } | |
182 if (size == 0) size = 1; | |
183 long addr = MallocStressTest.whiteBox.NMTMallocWithPseudoStack(size, r); | |
184 if (addr != 0) { | |
185 MallocMemory mem = new MallocMemory(addr, size); | |
186 synchronized(MallocStressTest.mallocd_memory) { | |
187 MallocStressTest.mallocd_memory.add(mem); | |
188 MallocStressTest.mallocd_total += size; | |
189 } | |
190 } else { | |
191 System.out.println("Out of malloc memory"); | |
192 break; | |
193 } | |
194 } | |
195 MallocStressTest.pause_count.incrementAndGet(); | |
196 } | |
197 } | |
198 | |
199 static class ReleaseThread extends Thread { | |
200 private Random random = new Random(); | |
201 ReleaseThread() { | |
202 this.setName("ReleaseThread"); | |
203 this.start(); | |
204 } | |
205 | |
206 public void run() { | |
207 while(true) { | |
208 switch(MallocStressTest.phase) { | |
209 case alloc: | |
210 slow_release(); | |
211 break; | |
212 case pause: | |
213 enter_pause(); | |
214 break; | |
215 case release: | |
216 quick_release(); | |
217 return; | |
218 } | |
219 } | |
220 } | |
221 | |
222 private void enter_pause() { | |
223 MallocStressTest.pause_count.incrementAndGet(); | |
224 while (MallocStressTest.phase != MallocStressTest.TestPhase.release) { | |
225 try { | |
226 synchronized(MallocStressTest.mallocd_memory) { | |
227 MallocStressTest.mallocd_memory.wait(10); | |
228 } | |
229 } catch (InterruptedException e) { | |
230 } | |
231 } | |
232 } | |
233 | |
234 private void quick_release() { | |
235 List<MallocMemory> free_list; | |
236 while (true) { | |
237 synchronized(MallocStressTest.mallocd_memory) { | |
238 if (MallocStressTest.mallocd_memory.isEmpty()) return; | |
239 int size = Math.min(MallocStressTest.mallocd_memory.size(), 5000); | |
240 List<MallocMemory> subList = MallocStressTest.mallocd_memory.subList(0, size); | |
241 free_list = new ArrayList<MallocMemory>(subList); | |
242 subList.clear(); | |
243 } | |
244 for (int index = 0; index < free_list.size(); index ++) { | |
245 MallocMemory mem = free_list.get(index); | |
246 MallocStressTest.whiteBox.NMTFree(mem.addr()); | |
247 } | |
248 } | |
249 } | |
250 | |
251 private void slow_release() { | |
252 try { | |
253 Thread.sleep(10); | |
254 } catch (InterruptedException e) { | |
255 } | |
256 synchronized(MallocStressTest.mallocd_memory) { | |
257 if (MallocStressTest.mallocd_memory.isEmpty()) return; | |
258 int n = Math.abs(random.nextInt()) % MallocStressTest.mallocd_memory.size(); | |
259 MallocMemory mem = mallocd_memory.remove(n); | |
260 MallocStressTest.whiteBox.NMTFree(mem.addr()); | |
261 MallocStressTest.mallocd_total -= mem.size(); | |
262 } | |
263 } | |
264 } | |
265 } |