Mercurial > hg > truffle
comparison test/runtime/memory/LargePages/TestLargePagesFlags.java @ 12832:263f2c796d6c
8024838: Significant slowdown due to transparent huge pages
Summary: Don't turn on transparent huge pages (-XX:+UseTransparentHugePages) unless explicitly specified on the command line. This has the effect that large pages are never turned on Linux unless the user has explicitly enabled any of the large pages flags: -XX:+UseLargePages, -XX:+UseTransparentHugePages, -XX:+UseHugeTLBFS, and -XX:+UseSHM.
Reviewed-by: jwilhelm, tschatzl, brutisso
author | stefank |
---|---|
date | Sat, 05 Oct 2013 10:14:58 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
12830:9b4d0569f2f4 | 12832:263f2c796d6c |
---|---|
1 /* | |
2 * Copyright (c) 2013, 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 /* @test TestLargePagesFlags | |
25 * @summary Tests how large pages are choosen depending on the given large pages flag combinations. | |
26 * @library /testlibrary | |
27 * @run main TestLargePagesFlags | |
28 */ | |
29 | |
30 import com.oracle.java.testlibrary.OutputAnalyzer; | |
31 import com.oracle.java.testlibrary.Platform; | |
32 import com.oracle.java.testlibrary.ProcessTools; | |
33 import java.util.ArrayList; | |
34 | |
35 public class TestLargePagesFlags { | |
36 | |
37 public static void main(String [] args) throws Exception { | |
38 if (!Platform.isLinux()) { | |
39 System.out.println("Skipping. TestLargePagesFlags has only been implemented for Linux."); | |
40 return; | |
41 } | |
42 | |
43 testUseTransparentHugePages(); | |
44 testUseHugeTLBFS(); | |
45 testUseSHM(); | |
46 testCombinations(); | |
47 } | |
48 | |
49 public static void testUseTransparentHugePages() throws Exception { | |
50 if (!canUse(UseTransparentHugePages(true))) { | |
51 System.out.println("Skipping testUseTransparentHugePages"); | |
52 return; | |
53 } | |
54 | |
55 // -XX:-UseLargePages overrides all other flags. | |
56 new FlagTester() | |
57 .use(UseLargePages(false), | |
58 UseTransparentHugePages(true)) | |
59 .expect( | |
60 UseLargePages(false), | |
61 UseTransparentHugePages(false), | |
62 UseHugeTLBFS(false), | |
63 UseSHM(false)); | |
64 | |
65 // Explicitly turn on UseTransparentHugePages. | |
66 new FlagTester() | |
67 .use(UseTransparentHugePages(true)) | |
68 .expect( | |
69 UseLargePages(true), | |
70 UseTransparentHugePages(true), | |
71 UseHugeTLBFS(false), | |
72 UseSHM(false)); | |
73 | |
74 new FlagTester() | |
75 .use(UseLargePages(true), | |
76 UseTransparentHugePages(true)) | |
77 .expect( | |
78 UseLargePages(true), | |
79 UseTransparentHugePages(true), | |
80 UseHugeTLBFS(false), | |
81 UseSHM(false)); | |
82 | |
83 // Setting a specific large pages flag will turn | |
84 // off heuristics to choose large pages type. | |
85 new FlagTester() | |
86 .use(UseLargePages(true), | |
87 UseTransparentHugePages(false)) | |
88 .expect( | |
89 UseLargePages(false), | |
90 UseTransparentHugePages(false), | |
91 UseHugeTLBFS(false), | |
92 UseSHM(false)); | |
93 | |
94 // Don't turn on UseTransparentHugePages | |
95 // unless the user explicitly asks for them. | |
96 new FlagTester() | |
97 .use(UseLargePages(true)) | |
98 .expect( | |
99 UseTransparentHugePages(false)); | |
100 } | |
101 | |
102 public static void testUseHugeTLBFS() throws Exception { | |
103 if (!canUse(UseHugeTLBFS(true))) { | |
104 System.out.println("Skipping testUseHugeTLBFS"); | |
105 return; | |
106 } | |
107 | |
108 // -XX:-UseLargePages overrides all other flags. | |
109 new FlagTester() | |
110 .use(UseLargePages(false), | |
111 UseHugeTLBFS(true)) | |
112 .expect( | |
113 UseLargePages(false), | |
114 UseTransparentHugePages(false), | |
115 UseHugeTLBFS(false), | |
116 UseSHM(false)); | |
117 | |
118 // Explicitly turn on UseHugeTLBFS. | |
119 new FlagTester() | |
120 .use(UseHugeTLBFS(true)) | |
121 .expect( | |
122 UseLargePages(true), | |
123 UseTransparentHugePages(false), | |
124 UseHugeTLBFS(true), | |
125 UseSHM(false)); | |
126 | |
127 new FlagTester() | |
128 .use(UseLargePages(true), | |
129 UseHugeTLBFS(true)) | |
130 .expect( | |
131 UseLargePages(true), | |
132 UseTransparentHugePages(false), | |
133 UseHugeTLBFS(true), | |
134 UseSHM(false)); | |
135 | |
136 // Setting a specific large pages flag will turn | |
137 // off heuristics to choose large pages type. | |
138 new FlagTester() | |
139 .use(UseLargePages(true), | |
140 UseHugeTLBFS(false)) | |
141 .expect( | |
142 UseLargePages(false), | |
143 UseTransparentHugePages(false), | |
144 UseHugeTLBFS(false), | |
145 UseSHM(false)); | |
146 | |
147 // Using UseLargePages will default to UseHugeTLBFS large pages. | |
148 new FlagTester() | |
149 .use(UseLargePages(true)) | |
150 .expect( | |
151 UseLargePages(true), | |
152 UseTransparentHugePages(false), | |
153 UseHugeTLBFS(true), | |
154 UseSHM(false)); | |
155 } | |
156 | |
157 public static void testUseSHM() throws Exception { | |
158 if (!canUse(UseSHM(true))) { | |
159 System.out.println("Skipping testUseSHM"); | |
160 return; | |
161 } | |
162 | |
163 // -XX:-UseLargePages overrides all other flags. | |
164 new FlagTester() | |
165 .use(UseLargePages(false), | |
166 UseSHM(true)) | |
167 .expect( | |
168 UseLargePages(false), | |
169 UseTransparentHugePages(false), | |
170 UseHugeTLBFS(false), | |
171 UseSHM(false)); | |
172 | |
173 // Explicitly turn on UseSHM. | |
174 new FlagTester() | |
175 .use(UseSHM(true)) | |
176 .expect( | |
177 UseLargePages(true), | |
178 UseTransparentHugePages(false), | |
179 UseHugeTLBFS(false), | |
180 UseSHM(true)) ; | |
181 | |
182 new FlagTester() | |
183 .use(UseLargePages(true), | |
184 UseSHM(true)) | |
185 .expect( | |
186 UseLargePages(true), | |
187 UseTransparentHugePages(false), | |
188 UseHugeTLBFS(false), | |
189 UseSHM(true)) ; | |
190 | |
191 // Setting a specific large pages flag will turn | |
192 // off heuristics to choose large pages type. | |
193 new FlagTester() | |
194 .use(UseLargePages(true), | |
195 UseSHM(false)) | |
196 .expect( | |
197 UseLargePages(false), | |
198 UseTransparentHugePages(false), | |
199 UseHugeTLBFS(false), | |
200 UseSHM(false)); | |
201 | |
202 // Setting UseLargePages can allow the system to choose | |
203 // UseHugeTLBFS instead of UseSHM, but never UseTransparentHugePages. | |
204 new FlagTester() | |
205 .use(UseLargePages(true)) | |
206 .expect( | |
207 UseLargePages(true), | |
208 UseTransparentHugePages(false)); | |
209 } | |
210 | |
211 public static void testCombinations() throws Exception { | |
212 if (!canUse(UseSHM(true)) || !canUse(UseHugeTLBFS(true))) { | |
213 System.out.println("Skipping testUseHugeTLBFSAndUseSHMCombination"); | |
214 return; | |
215 } | |
216 | |
217 // UseHugeTLBFS takes precedence over SHM. | |
218 | |
219 new FlagTester() | |
220 .use(UseLargePages(true), | |
221 UseHugeTLBFS(true), | |
222 UseSHM(true)) | |
223 .expect( | |
224 UseLargePages(true), | |
225 UseTransparentHugePages(false), | |
226 UseHugeTLBFS(true), | |
227 UseSHM(false)); | |
228 | |
229 new FlagTester() | |
230 .use(UseLargePages(true), | |
231 UseHugeTLBFS(false), | |
232 UseSHM(true)) | |
233 .expect( | |
234 UseLargePages(true), | |
235 UseTransparentHugePages(false), | |
236 UseHugeTLBFS(false), | |
237 UseSHM(true)); | |
238 | |
239 new FlagTester() | |
240 .use(UseLargePages(true), | |
241 UseHugeTLBFS(true), | |
242 UseSHM(false)) | |
243 .expect( | |
244 UseLargePages(true), | |
245 UseTransparentHugePages(false), | |
246 UseHugeTLBFS(true), | |
247 UseSHM(false)); | |
248 | |
249 new FlagTester() | |
250 .use(UseLargePages(true), | |
251 UseHugeTLBFS(false), | |
252 UseSHM(false)) | |
253 .expect( | |
254 UseLargePages(false), | |
255 UseTransparentHugePages(false), | |
256 UseHugeTLBFS(false), | |
257 UseSHM(false)); | |
258 | |
259 | |
260 if (!canUse(UseTransparentHugePages(true))) { | |
261 return; | |
262 } | |
263 | |
264 // UseTransparentHugePages takes precedence. | |
265 | |
266 new FlagTester() | |
267 .use(UseLargePages(true), | |
268 UseTransparentHugePages(true), | |
269 UseHugeTLBFS(true), | |
270 UseSHM(true)) | |
271 .expect( | |
272 UseLargePages(true), | |
273 UseTransparentHugePages(true), | |
274 UseHugeTLBFS(false), | |
275 UseSHM(false)); | |
276 | |
277 new FlagTester() | |
278 .use(UseTransparentHugePages(true), | |
279 UseHugeTLBFS(true), | |
280 UseSHM(true)) | |
281 .expect( | |
282 UseLargePages(true), | |
283 UseTransparentHugePages(true), | |
284 UseHugeTLBFS(false), | |
285 UseSHM(false)); | |
286 } | |
287 | |
288 private static class FlagTester { | |
289 private Flag [] useFlags; | |
290 | |
291 public FlagTester use(Flag... useFlags) { | |
292 this.useFlags = useFlags; | |
293 return this; | |
294 } | |
295 | |
296 public void expect(Flag... expectedFlags) throws Exception { | |
297 if (useFlags == null) { | |
298 throw new IllegalStateException("Must run use() before expect()"); | |
299 } | |
300 | |
301 OutputAnalyzer output = executeNewJVM(useFlags); | |
302 | |
303 for (Flag flag : expectedFlags) { | |
304 System.out.println("Looking for: " + flag.flagString()); | |
305 String strValue = output.firstMatch(".* " + flag.name() + " .* :?= (\\S+).*", 1); | |
306 | |
307 if (strValue == null) { | |
308 throw new RuntimeException("Flag " + flag.name() + " couldn't be found"); | |
309 } | |
310 | |
311 if (!flag.value().equals(strValue)) { | |
312 throw new RuntimeException("Wrong value for: " + flag.name() | |
313 + " expected: " + flag.value() | |
314 + " got: " + strValue); | |
315 } | |
316 } | |
317 | |
318 output.shouldHaveExitValue(0); | |
319 } | |
320 } | |
321 | |
322 private static OutputAnalyzer executeNewJVM(Flag... flags) throws Exception { | |
323 ArrayList<String> args = new ArrayList<>(); | |
324 for (Flag flag : flags) { | |
325 args.add(flag.flagString()); | |
326 } | |
327 args.add("-XX:+PrintFlagsFinal"); | |
328 args.add("-version"); | |
329 | |
330 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args.toArray(new String[args.size()])); | |
331 OutputAnalyzer output = new OutputAnalyzer(pb.start()); | |
332 | |
333 return output; | |
334 } | |
335 | |
336 private static boolean canUse(Flag flag) { | |
337 try { | |
338 new FlagTester().use(flag).expect(flag); | |
339 } catch (Exception e) { | |
340 return false; | |
341 } | |
342 | |
343 return true; | |
344 } | |
345 | |
346 private static Flag UseLargePages(boolean value) { | |
347 return new BooleanFlag("UseLargePages", value); | |
348 } | |
349 | |
350 private static Flag UseTransparentHugePages(boolean value) { | |
351 return new BooleanFlag("UseTransparentHugePages", value); | |
352 } | |
353 | |
354 private static Flag UseHugeTLBFS(boolean value) { | |
355 return new BooleanFlag("UseHugeTLBFS", value); | |
356 } | |
357 | |
358 private static Flag UseSHM(boolean value) { | |
359 return new BooleanFlag("UseSHM", value); | |
360 } | |
361 | |
362 private static class BooleanFlag implements Flag { | |
363 private String name; | |
364 private boolean value; | |
365 | |
366 BooleanFlag(String name, boolean value) { | |
367 this.name = name; | |
368 this.value = value; | |
369 } | |
370 | |
371 public String flagString() { | |
372 return "-XX:" + (value ? "+" : "-") + name; | |
373 } | |
374 | |
375 public String name() { | |
376 return name; | |
377 } | |
378 | |
379 public String value() { | |
380 return Boolean.toString(value); | |
381 } | |
382 } | |
383 | |
384 private static interface Flag { | |
385 public String flagString(); | |
386 public String name(); | |
387 public String value(); | |
388 } | |
389 } |