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 }