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 */
109 private static void createSubsystems(String[] line) {
110 if (line.length < 5) return;
111 Path p = Paths.get(line[4]);
112 String subsystemName = p.getFileName().toString();
113 if (subsystemName != null) {
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);
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() {
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]) {
|
1 /*
2 * Copyright (c) 2018, 2020, 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 */
109 private static void createSubsystems(String[] line) {
110 if (line.length < 5) return;
111 Path p = Paths.get(line[4]);
112 String subsystemName = p.getFileName().toString();
113 if (subsystemName != null) {
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 if (startPerCpu == null) {
130 startPerCpu = new long[0];
131 }
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(MetricsTesterCgroupV1::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(MetricsTesterCgroupV1::setPath);
144 lines.close();
145 } catch (IOException e) {
146 }
147 }
148
149 private static String getFileContents(Controller 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 null;
156 }
157 }
158
159 private static long getLongValueFromFile(Controller subSystem, String fileName) {
160 String data = getFileContents(subSystem, fileName);
161 return (data == null || data.isEmpty()) ? 0L : convertStringToLong(data);
162 }
163
164 private static long convertStringToLong(String strval) {
165 return CgroupMetricsTester.convertStringToLong(strval, Long.MAX_VALUE);
166 }
167
168 private static long getLongValueFromFile(Controller subSystem, String metric, String subMetric) {
169 String stats = getFileContents(subSystem, metric);
170 String[] tokens = stats.split("[\\r\\n]+");
171 for (int i = 0; i < tokens.length; i++) {
172 if (tokens[i].startsWith(subMetric)) {
173 String strval = tokens[i].split("\\s+")[1];
174 return convertStringToLong(strval);
175 }
176 }
177 return 0L;
178 }
179
180 private static double getDoubleValueFromFile(Controller subSystem, String fileName) {
181 String data = getFileContents(subSystem, fileName);
318
319 boolean oomKillEnabled = metrics.isMemoryOOMKillEnabled();
320 boolean newOomKillEnabled = getLongValueFromFile(Controller.MEMORY,
321 "memory.oom_control", "oom_kill_disable") == 0L ? true : false;
322 if (oomKillEnabled != newOomKillEnabled) {
323 throw new RuntimeException("Test failed for - " + Controller.MEMORY.value + ":"
324 + "memory.oom_control:oom_kill_disable" + ", expected ["
325 + oomKillEnabled + "], got [" + newOomKillEnabled + "]");
326 }
327 }
328
329 public void testCpuAccounting() {
330 Metrics metrics = Metrics.systemMetrics();
331 long oldVal = metrics.getCpuUsage();
332 long newVal = getLongValueFromFile(Controller.CPUACCT, "cpuacct.usage");
333
334 if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
335 warn(Controller.CPUACCT, "cpuacct.usage", oldVal, newVal);
336 }
337
338 String newValsStr = getFileContents(Controller.CPUACCT, "cpuacct.usage_percpu");
339 Long[] newVals = new Long[0];
340 if (newValsStr != null) {
341 newVals = Stream.of(newValsStr
342 .split("\\s+"))
343 .map(Long::parseLong)
344 .toArray(Long[]::new);
345 }
346 long[] oldValsPrim = metrics.getPerCpuUsage();
347 Long[] oldVals = LongStream.of(oldValsPrim == null ? new long[0] : oldValsPrim)
348 .boxed().toArray(Long[]::new);
349 for (int i = 0; i < oldVals.length; i++) {
350 if (!CgroupMetricsTester.compareWithErrorMargin(oldVals[i], newVals[i])) {
351 warn(Controller.CPUACCT, "cpuacct.usage_percpu", oldVals[i], newVals[i]);
352 }
353 }
354
355 oldVal = metrics.getCpuUserUsage();
356 newVal = getLongValueFromFile(Controller.CPUACCT, "cpuacct.stat", "user");
357 if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
358 warn(Controller.CPUACCT, "cpuacct.usage - user", oldVal, newVal);
359 }
360
361 oldVal = metrics.getCpuSystemUsage();
362 newVal = getLongValueFromFile(Controller.CPUACCT, "cpuacct.stat", "system");
363 if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
364 warn(Controller.CPUACCT, "cpuacct.usage - system", oldVal, newVal);
365 }
366 }
367
368 public void testCpuSchedulingMetrics() {
480 "blkio.throttle.io_service_bytes", "Total");
481 if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
482 fail(Controller.BLKIO, "blkio.throttle.io_service_bytes - Total",
483 oldVal, newVal);
484 }
485
486 oldVal = metrics.getBlkIOServiced();
487 newVal = getLongValueFromFile(Controller.BLKIO, "blkio.throttle.io_serviced", "Total");
488 if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) {
489 fail(Controller.BLKIO, "blkio.throttle.io_serviced - Total", oldVal, newVal);
490 }
491 }
492
493 public void testCpuConsumption() throws IOException, InterruptedException {
494 Metrics metrics = Metrics.systemMetrics();
495 // make system call
496 long newSysVal = metrics.getCpuSystemUsage();
497 long newUserVal = metrics.getCpuUserUsage();
498 long newUsage = metrics.getCpuUsage();
499 long[] newPerCpu = metrics.getPerCpuUsage();
500 if (newPerCpu == null) {
501 newPerCpu = new long[0];
502 }
503
504 // system/user CPU usage counters may be slowly increasing.
505 // allow for equal values for a pass
506 if (newSysVal < startSysVal) {
507 fail(Controller.CPU, "getCpuSystemUsage", newSysVal, startSysVal);
508 }
509
510 // system/user CPU usage counters may be slowly increasing.
511 // allow for equal values for a pass
512 if (newUserVal < startUserVal) {
513 fail(Controller.CPU, "getCpuUserUsage", newUserVal, startUserVal);
514 }
515
516 if (newUsage <= startUsage) {
517 fail(Controller.CPU, "getCpuUsage", newUsage, startUsage);
518 }
519
520 boolean success = false;
521 for (int i = 0; i < startPerCpu.length; i++) {
522 if (newPerCpu[i] > startPerCpu[i]) {
|