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