Thu, 31 Jan 2019 23:56:37 +0800
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 | } |