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