test/runtime/containers/docker/TestCPUAwareness.java

Thu, 31 Jan 2019 23:56:37 +0800

author
aoqi
date
Thu, 31 Jan 2019 23:56:37 +0800
changeset 9657
71aba4a921a0
parent 9421
6cfec782c42c
child 9992
1d9ed8dec94c
permissions
-rw-r--r--

8217597: [TESTBUG] old version docker does not support --cpus
Summary: "--cpus" is only available in Docker 1.13 and higher, and is the equivalent of setting both --cpu-period and --cpu-quota.
Reviewed-by: bobv, dholmes
Contributed-by: aoqi@loongson.cn

vaibhav@9421 1 /*
aoqi@9657 2 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
vaibhav@9421 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
vaibhav@9421 4 *
vaibhav@9421 5 * This code is free software; you can redistribute it and/or modify it
vaibhav@9421 6 * under the terms of the GNU General Public License version 2 only, as
vaibhav@9421 7 * published by the Free Software Foundation.
vaibhav@9421 8 *
vaibhav@9421 9 * This code is distributed in the hope that it will be useful, but WITHOUT
vaibhav@9421 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
vaibhav@9421 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
vaibhav@9421 12 * version 2 for more details (a copy is included in the LICENSE file that
vaibhav@9421 13 * accompanied this code).
vaibhav@9421 14 *
vaibhav@9421 15 * You should have received a copy of the GNU General Public License version
vaibhav@9421 16 * 2 along with this work; if not, write to the Free Software Foundation,
vaibhav@9421 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
vaibhav@9421 18 *
vaibhav@9421 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
vaibhav@9421 20 * or visit www.oracle.com if you need additional information or have any
vaibhav@9421 21 * questions.
vaibhav@9421 22 */
vaibhav@9421 23
vaibhav@9421 24
vaibhav@9421 25 /*
vaibhav@9421 26 * @test
vaibhav@9421 27 * @summary Test JVM's CPU resource awareness when running inside docker container
vaibhav@9421 28 * @library /testlibrary
vaibhav@9421 29 * @run driver TestCPUAwareness
vaibhav@9421 30 */
vaibhav@9421 31
vaibhav@9421 32 import java.util.List;
vaibhav@9421 33 import com.oracle.java.testlibrary.Common;
vaibhav@9421 34 import com.oracle.java.testlibrary.DockerTestUtils;
vaibhav@9421 35 import com.oracle.java.testlibrary.DockerRunOptions;
vaibhav@9421 36
vaibhav@9421 37 public class TestCPUAwareness {
vaibhav@9421 38 private static final String imageName = Common.imageName("cpu");
vaibhav@9421 39 private static final int availableCPUs = Runtime.getRuntime().availableProcessors();
vaibhav@9421 40
vaibhav@9421 41 public static void main(String[] args) throws Exception {
vaibhav@9421 42 if (!DockerTestUtils.canTestDocker()) {
vaibhav@9421 43 return;
vaibhav@9421 44 }
vaibhav@9421 45
vaibhav@9421 46 System.out.println("Test Environment: detected availableCPUs = " + availableCPUs);
vaibhav@9421 47 DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker");
vaibhav@9421 48
vaibhav@9421 49 try {
vaibhav@9421 50 // cpuset, period, shares, expected Active Processor Count
vaibhav@9421 51 testComboWithCpuSets();
vaibhav@9421 52
vaibhav@9421 53 // cpu shares - it should be safe to use CPU shares exceeding available CPUs
vaibhav@9421 54 testCpuShares(256, 1);
vaibhav@9421 55 testCpuShares(2048, 2);
vaibhav@9421 56 testCpuShares(4096, 4);
vaibhav@9421 57
vaibhav@9421 58 // leave one CPU for system and tools, otherwise this test may be unstable
vaibhav@9421 59 int maxNrOfAvailableCpus = availableCPUs - 1;
vaibhav@9421 60 for (int i=1; i < maxNrOfAvailableCpus; i = i * 2) {
vaibhav@9421 61 testCpus(i, i);
vaibhav@9421 62 }
vaibhav@9421 63
vaibhav@9421 64 // If ActiveProcessorCount is set, the VM should use it, regardless of other
vaibhav@9421 65 // container settings, host settings or available CPUs on the host.
vaibhav@9421 66 testActiveProcessorCount(1, 1);
vaibhav@9421 67 testActiveProcessorCount(2, 2);
vaibhav@9421 68
vaibhav@9421 69 // cpu quota and period
vaibhav@9421 70 testCpuQuotaAndPeriod(50*1000, 100*1000);
vaibhav@9421 71 testCpuQuotaAndPeriod(100*1000, 100*1000);
vaibhav@9421 72 testCpuQuotaAndPeriod(150*1000, 100*1000);
vaibhav@9421 73 testCpuQuotaAndPeriod(400*1000, 100*1000);
vaibhav@9421 74
vaibhav@9421 75 } finally {
vaibhav@9421 76 DockerTestUtils.removeDockerImage(imageName);
vaibhav@9421 77 }
vaibhav@9421 78 }
vaibhav@9421 79
vaibhav@9421 80
vaibhav@9421 81 private static void testComboWithCpuSets() throws Exception {
vaibhav@9421 82 String cpuSetStr = CPUSetsReader.readFromProcStatus("Cpus_allowed_list");
vaibhav@9421 83 System.out.println("cpuSetStr = " + cpuSetStr);
vaibhav@9421 84
vaibhav@9421 85 if (cpuSetStr == null) {
vaibhav@9421 86 System.out.printf("The cpuset test cases are skipped");
vaibhav@9421 87 } else {
vaibhav@9421 88 List<Integer> cpuSet = CPUSetsReader.parseCpuSet(cpuSetStr);
vaibhav@9421 89
vaibhav@9421 90 // Test subset of cpuset with one element
vaibhav@9421 91 if (cpuSet.size() >= 1) {
vaibhav@9421 92 String testCpuSet = CPUSetsReader.listToString(cpuSet, 1);
vaibhav@9421 93 testAPCCombo(testCpuSet, 200*1000, 100*1000, 4*1024, true, 1);
vaibhav@9421 94 }
vaibhav@9421 95
vaibhav@9421 96 // Test subset of cpuset with two elements
vaibhav@9421 97 if (cpuSet.size() >= 2) {
vaibhav@9421 98 String testCpuSet = CPUSetsReader.listToString(cpuSet, 2);
vaibhav@9421 99 testAPCCombo(testCpuSet, 200*1000, 100*1000, 4*1024, true, 2);
vaibhav@9421 100 testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, true, 2);
vaibhav@9421 101 testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1);
vaibhav@9421 102 }
vaibhav@9421 103
vaibhav@9421 104 // Test subset of cpuset with three elements
vaibhav@9421 105 if (cpuSet.size() >= 3) {
vaibhav@9421 106 String testCpuSet = CPUSetsReader.listToString(cpuSet, 3);
vaibhav@9421 107 testAPCCombo(testCpuSet, 100*1000, 100*1000, 2*1024, true, 1);
vaibhav@9421 108 testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, true, 2);
vaibhav@9421 109 testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1);
vaibhav@9421 110 }
vaibhav@9421 111 }
vaibhav@9421 112 }
vaibhav@9421 113
vaibhav@9421 114
vaibhav@9421 115 private static void testActiveProcessorCount(int valueToSet, int expectedValue) throws Exception {
vaibhav@9421 116 Common.logNewTestCase("Test ActiveProcessorCount: valueToSet = " + valueToSet);
vaibhav@9421 117
vaibhav@9421 118 DockerRunOptions opts = Common.newOpts(imageName)
vaibhav@9421 119 .addJavaOpts("-XX:ActiveProcessorCount=" + valueToSet, "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintActiveCpus");
vaibhav@9421 120 Common.run(opts)
vaibhav@9421 121 .shouldMatch("active processor count set by user.*" + expectedValue);
vaibhav@9421 122 }
vaibhav@9421 123
vaibhav@9421 124
vaibhav@9421 125 private static void testCpus(int valueToSet, int expectedTraceValue) throws Exception {
vaibhav@9421 126 Common.logNewTestCase("test cpus: " + valueToSet);
vaibhav@9421 127 DockerRunOptions opts = Common.newOpts(imageName)
aoqi@9657 128 .addDockerOpts("--cpu-period=" + 10000)
aoqi@9657 129 .addDockerOpts("--cpu-quota=" + valueToSet * 10000);
vaibhav@9421 130 Common.run(opts)
vaibhav@9421 131 .shouldMatch("active_processor_count.*" + expectedTraceValue);
vaibhav@9421 132 }
vaibhav@9421 133
vaibhav@9421 134
vaibhav@9421 135 // Expected active processor count can not exceed available CPU count
vaibhav@9421 136 private static int adjustExpectedAPCForAvailableCPUs(int expectedAPC) {
vaibhav@9421 137 if (expectedAPC > availableCPUs) {
vaibhav@9421 138 expectedAPC = availableCPUs;
vaibhav@9421 139 System.out.println("Adjusted expectedAPC = " + expectedAPC);
vaibhav@9421 140 }
vaibhav@9421 141 return expectedAPC;
vaibhav@9421 142 }
vaibhav@9421 143
vaibhav@9421 144
vaibhav@9421 145 private static void testCpuQuotaAndPeriod(int quota, int period)
vaibhav@9421 146 throws Exception {
vaibhav@9421 147 Common.logNewTestCase("test cpu quota and period: ");
vaibhav@9421 148 System.out.println("quota = " + quota);
vaibhav@9421 149 System.out.println("period = " + period);
vaibhav@9421 150
vaibhav@9421 151 int expectedAPC = (int) Math.ceil((float) quota / (float) period);
vaibhav@9421 152 System.out.println("expectedAPC = " + expectedAPC);
vaibhav@9421 153 expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC);
vaibhav@9421 154
vaibhav@9421 155 DockerRunOptions opts = Common.newOpts(imageName)
vaibhav@9421 156 .addDockerOpts("--cpu-period=" + period)
vaibhav@9421 157 .addDockerOpts("--cpu-quota=" + quota);
vaibhav@9421 158
vaibhav@9421 159 Common.run(opts)
vaibhav@9421 160 .shouldMatch("CPU Period is.*" + period)
vaibhav@9421 161 .shouldMatch("CPU Quota is.*" + quota)
vaibhav@9421 162 .shouldMatch("active_processor_count.*" + expectedAPC);
vaibhav@9421 163 }
vaibhav@9421 164
vaibhav@9421 165
vaibhav@9421 166 // Test correctess of automatically selected active processor cound
vaibhav@9421 167 private static void testAPCCombo(String cpuset, int quota, int period, int shares,
vaibhav@9421 168 boolean usePreferContainerQuotaForCPUCount,
vaibhav@9421 169 int expectedAPC) throws Exception {
vaibhav@9421 170 Common.logNewTestCase("test APC Combo");
vaibhav@9421 171 System.out.println("cpuset = " + cpuset);
vaibhav@9421 172 System.out.println("quota = " + quota);
vaibhav@9421 173 System.out.println("period = " + period);
vaibhav@9421 174 System.out.println("shares = " + period);
vaibhav@9421 175 System.out.println("usePreferContainerQuotaForCPUCount = " + usePreferContainerQuotaForCPUCount);
vaibhav@9421 176 System.out.println("expectedAPC = " + expectedAPC);
vaibhav@9421 177
vaibhav@9421 178 expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC);
vaibhav@9421 179
vaibhav@9421 180 DockerRunOptions opts = Common.newOpts(imageName)
vaibhav@9421 181 .addDockerOpts("--cpuset-cpus", "" + cpuset)
vaibhav@9421 182 .addDockerOpts("--cpu-period=" + period)
vaibhav@9421 183 .addDockerOpts("--cpu-quota=" + quota)
vaibhav@9421 184 .addDockerOpts("--cpu-shares=" + shares);
vaibhav@9421 185
vaibhav@9421 186 if (!usePreferContainerQuotaForCPUCount) opts.addJavaOpts("-XX:-PreferContainerQuotaForCPUCount");
vaibhav@9421 187
vaibhav@9421 188 Common.run(opts)
vaibhav@9421 189 .shouldMatch("active_processor_count.*" + expectedAPC);
vaibhav@9421 190 }
vaibhav@9421 191
vaibhav@9421 192
vaibhav@9421 193 private static void testCpuShares(int shares, int expectedAPC) throws Exception {
vaibhav@9421 194 Common.logNewTestCase("test cpu shares, shares = " + shares);
vaibhav@9421 195 System.out.println("expectedAPC = " + expectedAPC);
vaibhav@9421 196
vaibhav@9421 197 expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC);
vaibhav@9421 198
vaibhav@9421 199 DockerRunOptions opts = Common.newOpts(imageName)
vaibhav@9421 200 .addDockerOpts("--cpu-shares=" + shares);
vaibhav@9421 201 Common.run(opts)
vaibhav@9421 202 .shouldMatch("CPU Shares is.*" + shares)
vaibhav@9421 203 .shouldMatch("active_processor_count.*" + expectedAPC);
vaibhav@9421 204 }
vaibhav@9421 205 }

mercurial