Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion cgroup2/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,35 @@ func parseCgroupFromReader(r io.Reader) (string, error) {
return "", fmt.Errorf("cgroup path not found")
}

// ConvertCPUSharesToCgroupV2Value converts CPU shares, used by cgroup v1,
// to CPU weight, used by cgroup v2.
//
// Cgroup v1 CPU shares has a range of [2^1...2^18], i.e. [2...262144],
// and the default value is 1024.
//
// Cgroup v2 CPU weight has a range of [10^0...10^4], i.e. [1...10000],
// and the default value is 100.
//
// Taken from https://github.com/opencontainers/cgroups/blob/v0.0.5/utils.go#L417-L441
// (Apache License 2.0)
func ConvertCPUSharesToCgroupV2Value(cpuShares uint64) uint64 {
// The value of 0 means "unset".
if cpuShares == 0 {
return 0
}
if cpuShares <= 2 {
return 1
}
if cpuShares >= 262144 {
return 10000
}
l := math.Log2(float64(cpuShares))
// Quadratic function which fits min, max, and default.
exponent := (l*l+125*l)/612.0 - 7.0/34.0

return uint64(math.Ceil(math.Pow(10, exponent)))
}

// ToResources converts the oci LinuxResources struct into a
// v2 Resources type for use with this package.
//
Expand All @@ -159,7 +188,7 @@ func ToResources(spec *specs.LinuxResources) *Resources {
Mems: cpu.Mems,
}
if shares := cpu.Shares; shares != nil {
convertedWeight := 1 + ((*shares-2)*9999)/262142
convertedWeight := ConvertCPUSharesToCgroupV2Value(*shares)
resources.CPU.Weight = &convertedWeight
}
if period := cpu.Period; period != nil {
Expand Down
34 changes: 33 additions & 1 deletion cgroup2/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,38 @@ full avg10=1.00 avg60=1.01 avg300=1.00 total=157622356`
assert.Equal(t, &st.Full, &expected.Full)
}

// TestConvertCPUSharesToCgroupV2Value tests the ConvertCPUSharesToCgroupV2Value function.
// Taken from https://github.com/opencontainers/cgroups/blob/v0.0.5/utils_test.go#L537-L564
// (Apache License 2.0)
func TestConvertCPUSharesToCgroupV2Value(t *testing.T) {
const (
sharesMin = 2
sharesMax = 262144
sharesDef = 1024
weightMin = 1
weightMax = 10000
weightDef = 100
unset = 0
)
cases := map[uint64]uint64{
unset: unset,

sharesMin - 1: weightMin, // Below the minimum (out of range).
sharesMin: weightMin, // Minimum.
sharesMin + 1: weightMin + 1, // Just above the minimum.
sharesDef: weightDef, // Default.
sharesMax - 1: weightMax, // Just below the maximum.
sharesMax: weightMax, // Maximum.
sharesMax + 1: weightMax, // Above the maximum (out of range).
}
for shares, want := range cases {
got := ConvertCPUSharesToCgroupV2Value(shares)
if got != want {
t.Errorf("ConvertCPUSharesToCgroupV2Value(%d): got %d, want %d", shares, got, want)
}
}
}

func TestToResources(t *testing.T) {
var (
quota int64 = 8000
Expand All @@ -84,7 +116,7 @@ func TestToResources(t *testing.T) {
mem int64 = 300
swap int64 = 500
)
weight := 1 + ((shares-2)*9999)/262142
weight := ConvertCPUSharesToCgroupV2Value(shares)
res := specs.LinuxResources{
CPU: &specs.LinuxCPU{Quota: &quota, Period: &period, Shares: &shares},
Memory: &specs.LinuxMemory{Limit: &mem, Swap: &swap},
Expand Down
Loading