Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java
40942 views
1
/*
2
* Copyright (c) 2017, 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
*/
23
24
25
/*
26
* @test
27
* @key cgroups
28
* @summary Test JVM's CPU resource awareness when running inside docker container
29
* @requires docker.support
30
* @library /test/lib
31
* @modules java.base/jdk.internal.misc
32
* java.base/jdk.internal.platform
33
* java.management
34
* jdk.jartool/sun.tools.jar
35
* @build PrintContainerInfo CheckOperatingSystemMXBean
36
* @run driver TestCPUAwareness
37
*/
38
import java.util.List;
39
import jdk.test.lib.process.OutputAnalyzer;
40
import jdk.test.lib.containers.docker.Common;
41
import jdk.test.lib.containers.docker.DockerRunOptions;
42
import jdk.test.lib.containers.docker.DockerTestUtils;
43
import jdk.test.lib.containers.cgroup.CPUSetsReader;
44
45
public class TestCPUAwareness {
46
private static final String imageName = Common.imageName("cpu");
47
private static final int availableCPUs = Runtime.getRuntime().availableProcessors();
48
49
public static void main(String[] args) throws Exception {
50
if (!DockerTestUtils.canTestDocker()) {
51
return;
52
}
53
54
System.out.println("Test Environment: detected availableCPUs = " + availableCPUs);
55
DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker");
56
57
try {
58
// cpuset, period, shares, expected Active Processor Count
59
testComboWithCpuSets();
60
61
// cpu shares - it should be safe to use CPU shares exceeding available CPUs
62
testCpuShares(256, 1);
63
testCpuShares(2048, 2);
64
testCpuShares(4096, 4);
65
66
// leave one CPU for system and tools, otherwise this test may be unstable
67
int maxNrOfAvailableCpus = availableCPUs - 1;
68
for (int i=1; i < maxNrOfAvailableCpus; i = i * 2) {
69
testCpus(i, i);
70
}
71
72
// If ActiveProcessorCount is set, the VM should use it, regardless of other
73
// container settings, host settings or available CPUs on the host.
74
testActiveProcessorCount(1, 1);
75
testActiveProcessorCount(2, 2);
76
77
// cpu quota and period
78
testCpuQuotaAndPeriod(50*1000, 100*1000);
79
testCpuQuotaAndPeriod(100*1000, 100*1000);
80
testCpuQuotaAndPeriod(150*1000, 100*1000);
81
testCpuQuotaAndPeriod(400*1000, 100*1000);
82
83
testOperatingSystemMXBeanAwareness("0.5", "1");
84
testOperatingSystemMXBeanAwareness("1.0", "1");
85
if (availableCPUs > 2) {
86
testOperatingSystemMXBeanAwareness("1.2", "2");
87
testOperatingSystemMXBeanAwareness("1.8", "2");
88
testOperatingSystemMXBeanAwareness("2.0", "2");
89
}
90
91
} finally {
92
if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) {
93
DockerTestUtils.removeDockerImage(imageName);
94
}
95
}
96
}
97
98
99
private static void testComboWithCpuSets() throws Exception {
100
String cpuSetStr = CPUSetsReader.readFromProcStatus("Cpus_allowed_list");
101
System.out.println("cpuSetStr = " + cpuSetStr);
102
103
if (cpuSetStr == null) {
104
System.out.printf("The cpuset test cases are skipped");
105
} else {
106
List<Integer> cpuSet = CPUSetsReader.parseCpuSet(cpuSetStr);
107
108
// Test subset of cpuset with one element
109
if (cpuSet.size() >= 1) {
110
String testCpuSet = CPUSetsReader.listToString(cpuSet, 1);
111
testAPCCombo(testCpuSet, 200*1000, 100*1000, 4*1024, true, 1);
112
}
113
114
// Test subset of cpuset with two elements
115
if (cpuSet.size() >= 2) {
116
String testCpuSet = CPUSetsReader.listToString(cpuSet, 2);
117
testAPCCombo(testCpuSet, 200*1000, 100*1000, 4*1024, true, 2);
118
testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, true, 2);
119
testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1);
120
}
121
122
// Test subset of cpuset with three elements
123
if (cpuSet.size() >= 3) {
124
String testCpuSet = CPUSetsReader.listToString(cpuSet, 3);
125
testAPCCombo(testCpuSet, 100*1000, 100*1000, 2*1024, true, 1);
126
testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, true, 2);
127
testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1);
128
}
129
}
130
}
131
132
133
private static void testActiveProcessorCount(int valueToSet, int expectedValue) throws Exception {
134
Common.logNewTestCase("Test ActiveProcessorCount: valueToSet = " + valueToSet);
135
136
DockerRunOptions opts = Common.newOpts(imageName)
137
.addJavaOpts("-XX:ActiveProcessorCount=" + valueToSet, "-Xlog:os=trace");
138
Common.run(opts)
139
.shouldMatch("active processor count set by user.*" + expectedValue);
140
}
141
142
143
private static void testCpus(int valueToSet, int expectedTraceValue) throws Exception {
144
Common.logNewTestCase("test cpus: " + valueToSet);
145
DockerRunOptions opts = Common.newOpts(imageName)
146
.addDockerOpts("--cpu-period=" + 10000)
147
.addDockerOpts("--cpu-quota=" + valueToSet * 10000);
148
Common.run(opts)
149
.shouldMatch("active_processor_count.*" + expectedTraceValue);
150
}
151
152
153
// Expected active processor count can not exceed available CPU count
154
private static int adjustExpectedAPCForAvailableCPUs(int expectedAPC) {
155
if (expectedAPC > availableCPUs) {
156
expectedAPC = availableCPUs;
157
System.out.println("Adjusted expectedAPC = " + expectedAPC);
158
}
159
return expectedAPC;
160
}
161
162
163
private static void testCpuQuotaAndPeriod(int quota, int period)
164
throws Exception {
165
Common.logNewTestCase("test cpu quota and period: ");
166
System.out.println("quota = " + quota);
167
System.out.println("period = " + period);
168
169
int expectedAPC = (int) Math.ceil((float) quota / (float) period);
170
System.out.println("expectedAPC = " + expectedAPC);
171
expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC);
172
173
DockerRunOptions opts = Common.newOpts(imageName)
174
.addDockerOpts("--cpu-period=" + period)
175
.addDockerOpts("--cpu-quota=" + quota);
176
177
Common.run(opts)
178
.shouldMatch("CPU Period is.*" + period)
179
.shouldMatch("CPU Quota is.*" + quota)
180
.shouldMatch("active_processor_count.*" + expectedAPC);
181
}
182
183
184
// Test correctess of automatically selected active processor cound
185
private static void testAPCCombo(String cpuset, int quota, int period, int shares,
186
boolean usePreferContainerQuotaForCPUCount,
187
int expectedAPC) throws Exception {
188
Common.logNewTestCase("test APC Combo");
189
System.out.println("cpuset = " + cpuset);
190
System.out.println("quota = " + quota);
191
System.out.println("period = " + period);
192
System.out.println("shares = " + shares);
193
System.out.println("usePreferContainerQuotaForCPUCount = " + usePreferContainerQuotaForCPUCount);
194
System.out.println("expectedAPC = " + expectedAPC);
195
196
expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC);
197
198
DockerRunOptions opts = Common.newOpts(imageName)
199
.addDockerOpts("--cpuset-cpus", "" + cpuset)
200
.addDockerOpts("--cpu-period=" + period)
201
.addDockerOpts("--cpu-quota=" + quota)
202
.addDockerOpts("--cpu-shares=" + shares);
203
204
if (!usePreferContainerQuotaForCPUCount) opts.addJavaOpts("-XX:-PreferContainerQuotaForCPUCount");
205
206
Common.run(opts)
207
.shouldMatch("active_processor_count.*" + expectedAPC);
208
}
209
210
211
private static void testCpuShares(int shares, int expectedAPC) throws Exception {
212
Common.logNewTestCase("test cpu shares, shares = " + shares);
213
System.out.println("expectedAPC = " + expectedAPC);
214
215
expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC);
216
217
DockerRunOptions opts = Common.newOpts(imageName)
218
.addDockerOpts("--cpu-shares=" + shares);
219
OutputAnalyzer out = Common.run(opts);
220
// Cgroups v2 needs to do some scaling of raw shares values. Hence,
221
// 256 CPU shares come back as 264. Raw value written to cpu.weight
222
// is 10. The reason this works for >= 1024 shares value is because
223
// post-scaling the closest multiple of 1024 is found and returned.
224
//
225
// For values < 1024, this doesn't happen so loosen the match to a
226
// 3-digit number and ensure the active_processor_count is as
227
// expected.
228
if (shares < 1024) {
229
out.shouldMatch("CPU Shares is.*\\d{3}");
230
} else {
231
out.shouldMatch("CPU Shares is.*" + shares);
232
}
233
out.shouldMatch("active_processor_count.*" + expectedAPC);
234
}
235
236
private static void testOperatingSystemMXBeanAwareness(String cpuAllocation, String expectedCpus) throws Exception {
237
Common.logNewTestCase("Check OperatingSystemMXBean");
238
239
DockerRunOptions opts = Common.newOpts(imageName, "CheckOperatingSystemMXBean")
240
.addDockerOpts(
241
"--cpus", cpuAllocation
242
)
243
// CheckOperatingSystemMXBean uses Metrics (jdk.internal.platform) for
244
// diagnostics
245
.addJavaOpts("--add-exports")
246
.addJavaOpts("java.base/jdk.internal.platform=ALL-UNNAMED");
247
248
DockerTestUtils.dockerRunJava(opts)
249
.shouldHaveExitValue(0)
250
.shouldContain("Checking OperatingSystemMXBean")
251
.shouldContain("Runtime.availableProcessors: " + expectedCpus)
252
.shouldContain("OperatingSystemMXBean.getAvailableProcessors: " + expectedCpus)
253
.shouldMatch("OperatingSystemMXBean\\.getSystemCpuLoad: [0-9]+\\.[0-9]+")
254
.shouldMatch("OperatingSystemMXBean\\.getCpuLoad: [0-9]+\\.[0-9]+")
255
;
256
}
257
}
258
259