Skip to content

Add ConvertCPUSharesToCPUWeight - #17

Closed
kolyshkin wants to merge 1 commit into
opencontainers:mainfrom
kolyshkin:cpu-shares
Closed

Add ConvertCPUSharesToCPUWeight#17
kolyshkin wants to merge 1 commit into
opencontainers:mainfrom
kolyshkin:cpu-shares

Conversation

@kolyshkin

Copy link
Copy Markdown
Contributor

The existing function, ConvertCPUSharesToCgroupV2Value, do not have a way to return an error, and thus can accept invalid cgroup v1 (cpu-shares) values and can return invalid cgroup v2 (cpu-weight) values.

Add a new one, ConvertCPUSharesToCPUWeight, which is identical but can return meaningful errors. Mark the old one as deprecated. Amend the test case to test the new implementation (and, since both are using the same formula, existing implementation is tested, too, except for 0).

Related to opencontainers/runc#4755

The existing function, ConvertCPUSharesToCgroupV2Value, do not have a
way to return an error, and thus can accept invalid cgroup v1
(cpu-shares) values and can return invalid cgroup v2 (cpu-weight)
values.

Add a new one, ConvertCPUSharesToCPUWeight, which is identical but can
return meaningful errors. Mark the old one as deprecated. Amend the test
case to test the new implementation (and, since both are using the same
formula, existing implementation is tested, too, except for 0).

Related to runc issue 4755.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
@kolyshkin

Copy link
Copy Markdown
Contributor Author

@opencontainers/cgroups-maintainers PTAL

@haircommander

Copy link
Copy Markdown
Contributor

LGTM

@thaJeztah thaJeztah left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thx! found some minor issues, and left a suggestion

Comment thread utils.go
// the formula for cpuShares is y = (1 + ((x - 2) * 9999) / 262142)
// convert from [2-262144] to [1-10000]
// 262144 comes from Linux kernel definition "#define MAX_SHARES (1UL << 18)"
// there is need to convert from the cgroup v1 configuration to cgroup v2.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// there is need to convert from the cgroup v1 configuration to cgroup v2.
// there is a need to convert from the cgroup v1 configuration to cgroup v2.

Comment thread utils_test.go
t.Errorf("ConvertCPUSharesToCPUWeight(%d): expected error, got nil", tc.in)
}
} else if err != nil {
t.Errorf("ConvertCPUSharesToCPUWeight(%d): expected error, got nil", tc.in)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message here doesn't match what's expected (we do not expect an error here)

Comment thread utils_test.go
Comment on lines +548 to +549
for _, tc := range cases {
got, err := ConvertCPUSharesToCPUWeight(tc.in)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might as well make it a subtests; for the "should have no error" case, we can check both the error and the output.

for _, tc := range cases {
	t.Run(strconv.FormatUint(tc.in, 10), func(t *testing.T) {
		got, err := ConvertCPUSharesToCPUWeight(tc.in)
		if tc.isErr {
			if err == nil {
				t.Error("expected error, got nil")
			}
		} else {
			if err != nil {
				t.Errorf("expected no error, got: %v", err)
			}
			if got != tc.out {
				t.Errorf("want %d, got %d", tc.out, got)
			}
		}
	})
}

Or, if we want the tests to be more descriptive on intent, and make sure we're matching the right error;

func TestConvertCPUSharesToCPUWeight(t *testing.T) {
	cases := []struct {
		doc     string
		in, out uint64
		expErr  string
	}{
		{doc: "valid zero", in: 0, out: 0},
		{doc: "valid min value", in: 2, out: 1},
		{doc: "valid max value", in: 262144, out: 10000},
		{doc: "out of bound min", in: 1, expErr: "cpu-shares should be between 2 and 262144"},
		{doc: "out of bound max", in: 262145, expErr: "cpu-shares should be between 2 and 262144"},
	}
	for _, tc := range cases {
		t.Run(tc.doc, func(t *testing.T) {
			got, err := ConvertCPUSharesToCPUWeight(tc.in)
			if tc.expErr != "" {
				if err == nil || err.Error() != tc.expErr {
					t.Errorf("expected error %q, got %v", tc.expErr, err)
				}
				return
			}

			if err != nil {
				t.Errorf("expected no error, got: %v", err)
			}
			if got != tc.out {
				t.Errorf("want %d, got %d", tc.out, got)
			}
		})
	}
}

@kolyshkin

Copy link
Copy Markdown
Contributor Author

In the light of kubernetes/kubernetes#131216 and containers/crun#1767 I'm going to rework this.

@kolyshkin
kolyshkin marked this pull request as draft May 29, 2025 21:17
@kolyshkin

Copy link
Copy Markdown
Contributor Author

Closing in favor of #20

@kolyshkin kolyshkin closed this Jun 6, 2025
@kolyshkin
kolyshkin deleted the cpu-shares branch June 6, 2025 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants