Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8264136: Active processor count may be underreported #3177

Closed
Closed
Changes from all commits
Commits
File filter
Filter file types
Jump to
Jump to file
Failed to load files.

Always

Just for now

@@ -428,13 +428,16 @@ void CgroupSubsystemFactory::cleanup(CgroupInfo* cg_infos) {
* If neither shares or quotas have been specified, return the
* number of active processors in the system.
*
* If both shares and quotas have been specified, the results are
* based on the flag PreferContainerQuotaForCPUCount. If true,
* return the quota value. If false return the smallest value
* between shares or quotas.
* If the PreferContainerQuotaForCPUCount flag is set to true
* the result will be either the quota value (if quota is specified)
* or the number of active processors (if quota was not set).
* If the PreferContainerQuotaForCPUCount flag is set to false (or is unset)
* and both shares and quota are specified the smaller value will be
* chosen.
* If only one of shares or quota is specified than that value will
* be taken.
*
* If shares and/or quotas have been specified, the resulting number
* returned will never exceed the number of active processors.
* The resulting number returned will never exceed the number of active processors.
*
* return:
* number of CPUs
@@ -469,20 +472,23 @@ int CgroupSubsystem::active_processor_count() {
log_trace(os, container)("CPU Share count based on shares: %d", share_count);
}

// If both shares and quotas are setup results depend
// on flag PreferContainerQuotaForCPUCount.
// If true, limit CPU count to quota
// If false, use minimum of shares and quotas
if (quota_count !=0 && share_count != 0) {
if (PreferContainerQuotaForCPUCount) {
limit_count = quota_count;
} else {
// 1. If the PreferContainerQuotaForCPUCount flag is specified
// the CPU count will be limited by quota, if set.
// If quota is not set the limit will be equal to number
// of available CPUs derived from the cpu affinity information.
// 2. If the PreferContainerQuotaForCPUCount flag is not specified
// the result will be the minimum of non-zero values of the number
// of shares and quotas.
if (PreferContainerQuotaForCPUCount) {
limit_count = quota_count > 0 ? quota_count : cpu_count;
} else {
if (quota_count != 0 && share_count != 0) {
limit_count = MIN2(quota_count, share_count);
} else if (quota_count != 0) {
limit_count = quota_count;
} else if (share_count != 0) {
limit_count = share_count;
}
} else if (quota_count != 0) {
limit_count = quota_count;
} else if (share_count != 0) {
limit_count = share_count;
}

result = MIN2(cpu_count, limit_count);
@@ -59,9 +59,15 @@ public static void main(String[] args) throws Exception {
testComboWithCpuSets();

// cpu shares - it should be safe to use CPU shares exceeding available CPUs
testCpuShares(256, 1);
testCpuShares(2048, 2);
testCpuShares(4096, 4);
// If PreferContainerQuotaForCPUCount is set then specifying only shares
// should not affect the active processor count and it should be all the
// available CPUs.
testCpuShares(256, true, availableCPUs);
testCpuShares(256, false, 1);
testCpuShares(2048, true, availableCPUs);
testCpuShares(2048, false, 2);
testCpuShares(4096, true, availableCPUs);
testCpuShares(4096, false, 4);

// leave one CPU for system and tools, otherwise this test may be unstable
int maxNrOfAvailableCpus = availableCPUs - 1;
@@ -116,15 +122,19 @@ private static void testComboWithCpuSets() throws Exception {
String testCpuSet = CPUSetsReader.listToString(cpuSet, 2);
testAPCCombo(testCpuSet, 200*1000, 100*1000, 4*1024, true, 2);
testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, true, 2);
testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1);
testAPCCombo(testCpuSet, -1, -1, 1023, true, 2);
testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1);
testAPCCombo(testCpuSet, -1, -1, 1023, false, 1);
}

// Test subset of cpuset with three elements
if (cpuSet.size() >= 3) {
String testCpuSet = CPUSetsReader.listToString(cpuSet, 3);
testAPCCombo(testCpuSet, 100*1000, 100*1000, 2*1024, true, 1);
testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, true, 2);
testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1);
testAPCCombo(testCpuSet, -1, -1, 1023, true, 3);
testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1);
testAPCCombo(testCpuSet, -1, -1, 1023, false, 1);
}
}
}
@@ -197,9 +207,10 @@ private static void testAPCCombo(String cpuset, int quota, int period, int share

DockerRunOptions opts = Common.newOpts(imageName)
.addDockerOpts("--cpuset-cpus", "" + cpuset)
.addDockerOpts("--cpu-period=" + period)
.addDockerOpts("--cpu-quota=" + quota)
.addDockerOpts("--cpu-shares=" + shares);
if (period > -1 && quota > -1) {
opts.addDockerOpts("--cpu-period=" + period).addDockerOpts("--cpu-quota=" + quota);
}

if (!usePreferContainerQuotaForCPUCount) opts.addJavaOpts("-XX:-PreferContainerQuotaForCPUCount");

@@ -208,14 +219,16 @@ private static void testAPCCombo(String cpuset, int quota, int period, int share
}


private static void testCpuShares(int shares, int expectedAPC) throws Exception {
private static void testCpuShares(int shares, boolean usePreferContainerQuotaForCPUCount, int expectedAPC) throws Exception {
Common.logNewTestCase("test cpu shares, shares = " + shares);
System.out.println("expectedAPC = " + expectedAPC);

expectedAPC = adjustExpectedAPCForAvailableCPUs(expectedAPC);

DockerRunOptions opts = Common.newOpts(imageName)
.addDockerOpts("--cpu-shares=" + shares);
if (!usePreferContainerQuotaForCPUCount) opts.addJavaOpts("-XX:-PreferContainerQuotaForCPUCount");

OutputAnalyzer out = Common.run(opts);
// Cgroups v2 needs to do some scaling of raw shares values. Hence,
// 256 CPU shares come back as 264. Raw value written to cpu.weight
ProTip! Use n and p to navigate between commits in a pull request.