1 /* 2 * Copyright (c) 2018, 2019, 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 package jdk.test.lib.containers.cgroup; 25 26 import java.io.File; 27 import java.io.FileNotFoundException; 28 import java.io.IOException; 29 import java.math.BigInteger; 30 import java.nio.file.Files; 31 import java.nio.file.Path; 32 import java.nio.file.Paths; 33 import java.util.Arrays; 34 import java.util.HashMap; 35 import java.util.HashSet; 36 import java.util.Map; 37 import java.util.Scanner; 38 import java.util.Set; 39 import java.util.stream.Collectors; 40 import java.util.stream.IntStream; 41 import java.util.stream.LongStream; 42 import java.util.stream.Stream; 43 import jdk.internal.platform.Metrics; 44 45 public class MetricsTester { 46 47 private static final double ERROR_MARGIN = 0.1; 48 private static long unlimited_minimum = 0x7FFFFFFFFF000000L; 49 long startSysVal; 50 long startUserVal; 51 long startUsage; 52 long startPerCpu[]; 53 54 enum SubSystem { 55 MEMORY("memory"), 56 CPUSET("cpuset"), 57 CPU("cpu"), 58 CPUACCT("cpuacct"), 59 BLKIO("blkio"); 60 61 private String value; 62 63 SubSystem(String value) { 64 this.value = value; 65 } 66 67 public String value() { 68 return value; 69 } 70 } 71 72 private static final Set<String> allowedSubSystems = 73 Stream.of(SubSystem.values()).map(SubSystem::value).collect(Collectors.toSet()); 74 75 private static final Map<String, String[]> subSystemPaths = new HashMap<>(); 76 77 private static void setPath(String[] line) { 78 String cgroupPath = line[2]; 79 String[] subSystems = line[1].split(","); 80 81 for (String subSystem : subSystems) { 82 if (allowedSubSystems.contains(subSystem)) { 83 String[] paths = subSystemPaths.get(subSystem); 84 String finalPath = ""; 85 String root = paths[0]; 86 String mountPoint = paths[1]; 87 if (root != null && cgroupPath != null) { 88 if (root.equals("/")) { 89 if (!cgroupPath.equals("/")) { 90 finalPath = mountPoint + cgroupPath; 91 } else { 92 finalPath = mountPoint; 93 } 94 } else { 95 if (root.equals(cgroupPath)) { 96 finalPath = mountPoint; 97 } else { 98 if (cgroupPath.startsWith(root)) { 99 if (cgroupPath.length() > root.length()) { 100 String cgroupSubstr = cgroupPath.substring(root.length()); 101 finalPath = mountPoint + cgroupSubstr; 102 } 103 } 104 } 105 } 106 } 107 subSystemPaths.put(subSystem, new String[]{finalPath, mountPoint}); 108 } 109 } 110 } 111 112 private static void createSubsystems(String[] line) { 113 if (line.length < 5) return; 114 Path p = Paths.get(line[4]); 115 String subsystemName = p.getFileName().toString(); 116 if (subsystemName != null) { 117 for (String subSystem : subsystemName.split(",")) { 118 if (allowedSubSystems.contains(subSystem)) { 119 subSystemPaths.put(subSystem, new String[]{line[3], line[4]}); 120 } 121 } 122 } 123 } 124 125 public void setup() { 126 Metrics metrics = Metrics.systemMetrics(); 127 // Initialize CPU usage metrics before we do any testing. 128 startSysVal = metrics.getCpuSystemUsage(); 129 startUserVal = metrics.getCpuUserUsage(); 130 startUsage = metrics.getCpuUsage(); 131 startPerCpu = metrics.getPerCpuUsage(); 132 133 try { 134 Stream<String> lines = Files.lines(Paths.get("/proc/self/mountinfo")); 135 lines.filter(line -> line.contains(" - cgroup cgroup ")) 136 .map(line -> line.split(" ")) 137 .forEach(MetricsTester::createSubsystems); 138 lines.close(); 139 140 lines = Files.lines(Paths.get("/proc/self/cgroup")); 141 lines.map(line -> line.split(":")) 142 .filter(line -> (line.length >= 3)) 143 .forEach(MetricsTester::setPath); 144 lines.close(); 145 } catch (IOException e) { 146 } 147 } 148 149 private static String getFileContents(SubSystem subSystem, String fileName) { 150 String fname = subSystemPaths.get(subSystem.value())[0] + File.separator + fileName; 151 try { 152 return new Scanner(new File(fname)).useDelimiter("\\Z").next(); 153 } catch (FileNotFoundException e) { 154 System.err.println("Unable to open : " + fname); 155 return ""; 156 } 157 } 158 159 private static long getLongValueFromFile(SubSystem subSystem, String fileName) { 160 String data = getFileContents(subSystem, fileName); 161 return data.isEmpty() ? 0L : convertStringToLong(data); 162 } 163 164 private static long convertStringToLong(String strval) { 165 long retval = 0; 166 if (strval == null) return 0L; 167 168 try { 169 retval = Long.parseLong(strval); 170 } catch (NumberFormatException e) { 171 // For some properties (e.g. memory.limit_in_bytes) we may overflow the range of signed long. 172 // In this case, return Long.MAX_VALUE 173 BigInteger b = new BigInteger(strval); 174 if (b.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { 175 return Long.MAX_VALUE; 176 } 177 } 178 return retval; 179 } 180 181 private static long getLongValueFromFile(SubSystem subSystem, String metric, String subMetric) { 182 String stats = getFileContents(subSystem, metric); 183 String[] tokens = stats.split("[\\r\\n]+"); 184 for (int i = 0; i < tokens.length; i++) { 185 if (tokens[i].startsWith(subMetric)) { 186 String strval = tokens[i].split("\\s+")[1]; 187 return convertStringToLong(strval); 188 } 189 } 190 return 0L; 191 } 192 193 private static double getDoubleValueFromFile(SubSystem subSystem, String fileName) { 194 String data = getFileContents(subSystem, fileName); 195 return data.isEmpty() ? 0.0 : Double.parseDouble(data); 196 } 197 198 private boolean compareWithErrorMargin(long oldVal, long newVal) { 199 return Math.abs(oldVal - newVal) <= Math.abs(oldVal * ERROR_MARGIN); 200 } 201 202 private boolean compareWithErrorMargin(double oldVal, double newVal) { 203 return Math.abs(oldVal - newVal) <= Math.abs(oldVal * ERROR_MARGIN); 204 } 205 206 private static void fail(SubSystem system, String metric, long oldVal, long testVal) { 207 throw new RuntimeException("Test failed for - " + system.value + ":" 208 + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); 209 } 210 211 private static void fail(SubSystem system, String metric, String oldVal, String testVal) { 212 throw new RuntimeException("Test failed for - " + system.value + ":" 213 + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); 214 } 215 216 private static void fail(SubSystem system, String metric, double oldVal, double testVal) { 217 throw new RuntimeException("Test failed for - " + system.value + ":" 218 + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); 219 } 220 221 private static void fail(SubSystem system, String metric, boolean oldVal, boolean testVal) { 222 throw new RuntimeException("Test failed for - " + system.value + ":" 223 + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); 224 } 225 226 private static void warn(SubSystem system, String metric, long oldVal, long testVal) { 227 System.err.println("Warning - " + system.value + ":" + metric 228 + ", expected [" + oldVal + "], got [" + testVal + "]"); 229 } 230 231 public void testMemorySubsystem() { 232 Metrics metrics = Metrics.systemMetrics(); 233 234 // User Memory 235 long oldVal = metrics.getMemoryFailCount(); 236 long newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.failcnt"); 237 if (!compareWithErrorMargin(oldVal, newVal)) { 238 fail(SubSystem.MEMORY, "memory.failcnt", oldVal, newVal); 239 } 240 241 oldVal = metrics.getMemoryLimit(); 242 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.limit_in_bytes"); 243 newVal = newVal > unlimited_minimum ? -1L : newVal; 244 if (!compareWithErrorMargin(oldVal, newVal)) { 245 fail(SubSystem.MEMORY, "memory.limit_in_bytes", oldVal, newVal); 246 } 247 248 oldVal = metrics.getMemoryMaxUsage(); 249 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.max_usage_in_bytes"); 250 if (!compareWithErrorMargin(oldVal, newVal)) { 251 fail(SubSystem.MEMORY, "memory.max_usage_in_bytes", oldVal, newVal); 252 } 253 254 oldVal = metrics.getMemoryUsage(); 255 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.usage_in_bytes"); 256 if (!compareWithErrorMargin(oldVal, newVal)) { 257 fail(SubSystem.MEMORY, "memory.usage_in_bytes", oldVal, newVal); 258 } 259 260 // Kernel memory 261 oldVal = metrics.getKernelMemoryFailCount(); 262 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.failcnt"); 263 if (!compareWithErrorMargin(oldVal, newVal)) { 264 fail(SubSystem.MEMORY, "memory.kmem.failcnt", oldVal, newVal); 265 } 266 267 oldVal = metrics.getKernelMemoryLimit(); 268 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.limit_in_bytes"); 269 newVal = newVal > unlimited_minimum ? -1L : newVal; 270 if (!compareWithErrorMargin(oldVal, newVal)) { 271 fail(SubSystem.MEMORY, "memory.kmem.limit_in_bytes", oldVal, newVal); 272 } 273 274 oldVal = metrics.getKernelMemoryMaxUsage(); 275 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.max_usage_in_bytes"); 276 if (!compareWithErrorMargin(oldVal, newVal)) { 277 fail(SubSystem.MEMORY, "memory.kmem.max_usage_in_bytes", oldVal, newVal); 278 } 279 280 oldVal = metrics.getKernelMemoryUsage(); 281 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.usage_in_bytes"); 282 if (!compareWithErrorMargin(oldVal, newVal)) { 283 fail(SubSystem.MEMORY, "memory.kmem.usage_in_bytes", oldVal, newVal); 284 } 285 286 //TCP Memory 287 oldVal = metrics.getTcpMemoryFailCount(); 288 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.failcnt"); 289 if (!compareWithErrorMargin(oldVal, newVal)) { 290 fail(SubSystem.MEMORY, "memory.kmem.tcp.failcnt", oldVal, newVal); 291 } 292 293 oldVal = metrics.getTcpMemoryLimit(); 294 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.limit_in_bytes"); 295 newVal = newVal > unlimited_minimum ? -1L : newVal; 296 if (!compareWithErrorMargin(oldVal, newVal)) { 297 fail(SubSystem.MEMORY, "memory.kmem.tcp.limit_in_bytes", oldVal, newVal); 298 } 299 300 oldVal = metrics.getTcpMemoryMaxUsage(); 301 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.max_usage_in_bytes"); 302 if (!compareWithErrorMargin(oldVal, newVal)) { 303 fail(SubSystem.MEMORY, "memory.kmem.tcp.max_usage_in_bytes", oldVal, newVal); 304 } 305 306 oldVal = metrics.getTcpMemoryUsage(); 307 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.usage_in_bytes"); 308 if (!compareWithErrorMargin(oldVal, newVal)) { 309 fail(SubSystem.MEMORY, "memory.kmem.tcp.usage_in_bytes", oldVal, newVal); 310 } 311 312 // Memory and Swap 313 oldVal = metrics.getMemoryAndSwapFailCount(); 314 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.failcnt"); 315 if (!compareWithErrorMargin(oldVal, newVal)) { 316 fail(SubSystem.MEMORY, "memory.memsw.failcnt", oldVal, newVal); 317 } 318 319 oldVal = metrics.getMemoryAndSwapLimit(); 320 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.limit_in_bytes"); 321 newVal = newVal > unlimited_minimum ? -1L : newVal; 322 if (!compareWithErrorMargin(oldVal, newVal)) { 323 fail(SubSystem.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal); 324 } 325 326 oldVal = metrics.getMemoryAndSwapMaxUsage(); 327 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes"); 328 if (!compareWithErrorMargin(oldVal, newVal)) { 329 fail(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal); 330 } 331 332 oldVal = metrics.getMemoryAndSwapUsage(); 333 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.usage_in_bytes"); 334 if (!compareWithErrorMargin(oldVal, newVal)) { 335 fail(SubSystem.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal); 336 } 337 338 oldVal = metrics.getMemorySoftLimit(); 339 newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.soft_limit_in_bytes"); 340 newVal = newVal > unlimited_minimum ? -1L : newVal; 341 if (!compareWithErrorMargin(oldVal, newVal)) { 342 fail(SubSystem.MEMORY, "memory.soft_limit_in_bytes", oldVal, newVal); 343 } 344 345 boolean oomKillEnabled = metrics.isMemoryOOMKillEnabled(); 346 boolean newOomKillEnabled = getLongValueFromFile(SubSystem.MEMORY, 347 "memory.oom_control", "oom_kill_disable") == 0L ? true : false; 348 if (oomKillEnabled != newOomKillEnabled) { 349 throw new RuntimeException("Test failed for - " + SubSystem.MEMORY.value + ":" 350 + "memory.oom_control:oom_kill_disable" + ", expected [" 351 + oomKillEnabled + "], got [" + newOomKillEnabled + "]"); 352 } 353 } 354 355 public void testCpuAccounting() { 356 Metrics metrics = Metrics.systemMetrics(); 357 long oldVal = metrics.getCpuUsage(); 358 long newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpuacct.usage"); 359 360 if (!compareWithErrorMargin(oldVal, newVal)) { 361 warn(SubSystem.CPUACCT, "cpuacct.usage", oldVal, newVal); 362 } 363 364 Long[] newVals = Stream.of(getFileContents(SubSystem.CPUACCT, "cpuacct.usage_percpu") 365 .split("\\s+")) 366 .map(Long::parseLong) 367 .toArray(Long[]::new); 368 Long[] oldVals = LongStream.of(metrics.getPerCpuUsage()).boxed().toArray(Long[]::new); 369 for (int i = 0; i < oldVals.length; i++) { 370 if (!compareWithErrorMargin(oldVals[i], newVals[i])) { 371 warn(SubSystem.CPUACCT, "cpuacct.usage_percpu", oldVals[i], newVals[i]); 372 } 373 } 374 375 oldVal = metrics.getCpuUserUsage(); 376 newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpuacct.stat", "user"); 377 if (!compareWithErrorMargin(oldVal, newVal)) { 378 warn(SubSystem.CPUACCT, "cpuacct.usage - user", oldVal, newVal); 379 } 380 381 oldVal = metrics.getCpuSystemUsage(); 382 newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpuacct.stat", "system"); 383 if (!compareWithErrorMargin(oldVal, newVal)) { 384 warn(SubSystem.CPUACCT, "cpuacct.usage - system", oldVal, newVal); 385 } 386 } 387 388 public void testCpuSchedulingMetrics() { 389 Metrics metrics = Metrics.systemMetrics(); 390 long oldVal = metrics.getCpuPeriod(); 391 long newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.cfs_period_us"); 392 if (!compareWithErrorMargin(oldVal, newVal)) { 393 fail(SubSystem.CPUACCT, "cpu.cfs_period_us", oldVal, newVal); 394 } 395 396 oldVal = metrics.getCpuQuota(); 397 newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.cfs_quota_us"); 398 if (!compareWithErrorMargin(oldVal, newVal)) { 399 fail(SubSystem.CPUACCT, "cpu.cfs_quota_us", oldVal, newVal); 400 } 401 402 oldVal = metrics.getCpuShares(); 403 newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.shares"); 404 if (newVal == 0 || newVal == 1024) newVal = -1; 405 if (!compareWithErrorMargin(oldVal, newVal)) { 406 fail(SubSystem.CPUACCT, "cpu.shares", oldVal, newVal); 407 } 408 409 oldVal = metrics.getCpuNumPeriods(); 410 newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.stat", "nr_periods"); 411 if (!compareWithErrorMargin(oldVal, newVal)) { 412 fail(SubSystem.CPUACCT, "cpu.stat - nr_periods", oldVal, newVal); 413 } 414 415 oldVal = metrics.getCpuNumThrottled(); 416 newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.stat", "nr_throttled"); 417 if (!compareWithErrorMargin(oldVal, newVal)) { 418 fail(SubSystem.CPUACCT, "cpu.stat - nr_throttled", oldVal, newVal); 419 } 420 421 oldVal = metrics.getCpuThrottledTime(); 422 newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.stat", "throttled_time"); 423 if (!compareWithErrorMargin(oldVal, newVal)) { 424 fail(SubSystem.CPUACCT, "cpu.stat - throttled_time", oldVal, newVal); 425 } 426 } 427 428 public void testCpuSets() { 429 Metrics metrics = Metrics.systemMetrics(); 430 Integer[] oldVal = Arrays.stream(metrics.getCpuSetCpus()).boxed().toArray(Integer[]::new); 431 Arrays.sort(oldVal); 432 433 String cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.cpus"); 434 // Parse range string in the format 1,2-6,7 435 Integer[] newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { 436 if (a.contains("-")) { 437 String[] range = a.split("-"); 438 return IntStream.rangeClosed(Integer.parseInt(range[0]), 439 Integer.parseInt(range[1])).boxed(); 440 } else { 441 return Stream.of(Integer.parseInt(a)); 442 } 443 }).toArray(Integer[]::new); 444 Arrays.sort(newVal); 445 if (Arrays.compare(oldVal, newVal) != 0) { 446 fail(SubSystem.CPUSET, "cpuset.cpus", Arrays.toString(oldVal), 447 Arrays.toString(newVal)); 448 } 449 450 int [] cpuSets = metrics.getEffectiveCpuSetCpus(); 451 452 // Skip this test if this metric is supported on this platform 453 if (cpuSets.length != 0) { 454 oldVal = Arrays.stream(cpuSets).boxed().toArray(Integer[]::new); 455 Arrays.sort(oldVal); 456 cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.effective_cpus"); 457 newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { 458 if (a.contains("-")) { 459 String[] range = a.split("-"); 460 return IntStream.rangeClosed(Integer.parseInt(range[0]), 461 Integer.parseInt(range[1])).boxed(); 462 } else { 463 return Stream.of(Integer.parseInt(a)); 464 } 465 }).toArray(Integer[]::new); 466 Arrays.sort(newVal); 467 if (Arrays.compare(oldVal, newVal) != 0) { 468 fail(SubSystem.CPUSET, "cpuset.effective_cpus", Arrays.toString(oldVal), 469 Arrays.toString(newVal)); 470 } 471 } 472 473 oldVal = Arrays.stream(metrics.getCpuSetMems()).boxed().toArray(Integer[]::new); 474 Arrays.sort(oldVal); 475 cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.mems"); 476 newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { 477 if (a.contains("-")) { 478 String[] range = a.split("-"); 479 return IntStream.rangeClosed(Integer.parseInt(range[0]), 480 Integer.parseInt(range[1])).boxed(); 481 } else { 482 return Stream.of(Integer.parseInt(a)); 483 } 484 }).toArray(Integer[]::new); 485 Arrays.sort(newVal); 486 if (Arrays.compare(oldVal, newVal) != 0) { 487 fail(SubSystem.CPUSET, "cpuset.mems", Arrays.toString(oldVal), 488 Arrays.toString(newVal)); 489 } 490 491 int [] cpuSetMems = metrics.getEffectiveCpuSetMems(); 492 493 // Skip this test if this metric is supported on this platform 494 if (cpuSetMems.length != 0) { 495 oldVal = Arrays.stream(cpuSetMems).boxed().toArray(Integer[]::new); 496 Arrays.sort(oldVal); 497 cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.effective_mems"); 498 newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { 499 if (a.contains("-")) { 500 String[] range = a.split("-"); 501 return IntStream.rangeClosed(Integer.parseInt(range[0]), 502 Integer.parseInt(range[1])).boxed(); 503 } else { 504 return Stream.of(Integer.parseInt(a)); 505 } 506 }).toArray(Integer[]::new); 507 Arrays.sort(newVal); 508 if (Arrays.compare(oldVal, newVal) != 0) { 509 fail(SubSystem.CPUSET, "cpuset.effective_mems", Arrays.toString(oldVal), 510 Arrays.toString(newVal)); 511 } 512 } 513 514 double oldValue = metrics.getCpuSetMemoryPressure(); 515 double newValue = getDoubleValueFromFile(SubSystem.CPUSET, "cpuset.memory_pressure"); 516 if (!compareWithErrorMargin(oldValue, newValue)) { 517 fail(SubSystem.CPUSET, "cpuset.memory_pressure", oldValue, newValue); 518 } 519 520 boolean oldV = metrics.isCpuSetMemoryPressureEnabled(); 521 boolean newV = getLongValueFromFile(SubSystem.CPUSET, 522 "cpuset.memory_pressure_enabled") == 1 ? true : false; 523 if (oldV != newV) { 524 fail(SubSystem.CPUSET, "cpuset.memory_pressure_enabled", oldV, newV); 525 } 526 } 527 528 public void testBlkIO() { 529 Metrics metrics = Metrics.systemMetrics(); 530 long oldVal = metrics.getBlkIOServiceCount(); 531 long newVal = getLongValueFromFile(SubSystem.BLKIO, 532 "blkio.throttle.io_service_bytes", "Total"); 533 if (!compareWithErrorMargin(oldVal, newVal)) { 534 fail(SubSystem.BLKIO, "blkio.throttle.io_service_bytes - Total", 535 oldVal, newVal); 536 } 537 538 oldVal = metrics.getBlkIOServiced(); 539 newVal = getLongValueFromFile(SubSystem.BLKIO, "blkio.throttle.io_serviced", "Total"); 540 if (!compareWithErrorMargin(oldVal, newVal)) { 541 fail(SubSystem.BLKIO, "blkio.throttle.io_serviced - Total", oldVal, newVal); 542 } 543 } 544 545 public void testCpuConsumption() throws IOException, InterruptedException { 546 Metrics metrics = Metrics.systemMetrics(); 547 // make system call 548 long newSysVal = metrics.getCpuSystemUsage(); 549 long newUserVal = metrics.getCpuUserUsage(); 550 long newUsage = metrics.getCpuUsage(); 551 long[] newPerCpu = metrics.getPerCpuUsage(); 552 553 // system/user CPU usage counters may be slowly increasing. 554 // allow for equal values for a pass 555 if (newSysVal < startSysVal) { 556 fail(SubSystem.CPU, "getCpuSystemUsage", newSysVal, startSysVal); 557 } 558 559 // system/user CPU usage counters may be slowly increasing. 560 // allow for equal values for a pass 561 if (newUserVal < startUserVal) { 562 fail(SubSystem.CPU, "getCpuUserUsage", newUserVal, startUserVal); 563 } 564 565 if (newUsage <= startUsage) { 566 fail(SubSystem.CPU, "getCpuUsage", newUsage, startUsage); 567 } 568 569 boolean success = false; 570 for (int i = 0; i < startPerCpu.length; i++) { 571 if (newPerCpu[i] > startPerCpu[i]) { 572 success = true; 573 break; 574 } 575 } 576 577 if(!success) fail(SubSystem.CPU, "getPerCpuUsage", Arrays.toString(newPerCpu), 578 Arrays.toString(startPerCpu)); 579 } 580 581 public void testMemoryUsage() throws Exception { 582 Metrics metrics = Metrics.systemMetrics(); 583 long memoryMaxUsage = metrics.getMemoryMaxUsage(); 584 long memoryUsage = metrics.getMemoryUsage(); 585 long newMemoryMaxUsage = 0, newMemoryUsage = 0; 586 587 // allocate memory in a loop and check more than once for new values 588 // otherwise we might see seldom the effect of decreasing new memory values 589 // e.g. because the system could free up memory 590 byte[][] bytes = new byte[32][]; 591 for (int i = 0; i < 32; i++) { 592 bytes[i] = new byte[8*1024*1024]; 593 newMemoryUsage = metrics.getMemoryUsage(); 594 if (newMemoryUsage > memoryUsage) { 595 break; 596 } 597 } 598 newMemoryMaxUsage = metrics.getMemoryMaxUsage(); 599 600 if (newMemoryMaxUsage < memoryMaxUsage) { 601 fail(SubSystem.MEMORY, "getMemoryMaxUsage", memoryMaxUsage, 602 newMemoryMaxUsage); 603 } 604 605 if (newMemoryUsage < memoryUsage) { 606 fail(SubSystem.MEMORY, "getMemoryUsage", memoryUsage, newMemoryUsage); 607 } 608 } 609 610 public static void main(String[] args) throws Exception { 611 // If cgroups is not configured, report success 612 Metrics metrics = Metrics.systemMetrics(); 613 if (metrics == null) { 614 System.out.println("TEST PASSED!!!"); 615 return; 616 } 617 618 MetricsTester metricsTester = new MetricsTester(); 619 metricsTester.setup(); 620 metricsTester.testCpuAccounting(); 621 metricsTester.testCpuSchedulingMetrics(); 622 metricsTester.testCpuSets(); 623 metricsTester.testMemorySubsystem(); 624 metricsTester.testBlkIO(); 625 metricsTester.testCpuConsumption(); 626 metricsTester.testMemoryUsage(); 627 System.out.println("TEST PASSED!!!"); 628 } 629 }