Skip to content

Commit 33e090f

Browse files
authored
Merge pull request #20 from kolyshkin/cpu-shares-2
ConvertCPUSharesToCgroupV2Value: improve
2 parents 9657f5a + 75f91bd commit 33e090f

File tree

2 files changed

+43
-13
lines changed

2 files changed

+43
-13
lines changed

utils.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"errors"
66
"fmt"
77
"io"
8+
"math"
89
"os"
910
"path/filepath"
1011
"strconv"
@@ -413,16 +414,30 @@ func WriteCgroupProc(dir string, pid int) error {
413414
return err
414415
}
415416

416-
// Since the OCI spec is designed for cgroup v1, in some cases
417-
// there is need to convert from the cgroup v1 configuration to cgroup v2
418-
// the formula for cpuShares is y = (1 + ((x - 2) * 9999) / 262142)
419-
// convert from [2-262144] to [1-10000]
420-
// 262144 comes from Linux kernel definition "#define MAX_SHARES (1UL << 18)"
417+
// ConvertCPUSharesToCgroupV2Value converts CPU shares, used by cgroup v1,
418+
// to CPU weight, used by cgroup v2.
419+
//
420+
// Cgroup v1 CPU shares has a range of [2^1...2^18], i.e. [2...262144],
421+
// and the default value is 1024.
422+
//
423+
// Cgroup v2 CPU weight has a range of [10^0...10^4], i.e. [1...10000],
424+
// and the default value is 100.
421425
func ConvertCPUSharesToCgroupV2Value(cpuShares uint64) uint64 {
426+
// The value of 0 means "unset".
422427
if cpuShares == 0 {
423428
return 0
424429
}
425-
return (1 + ((cpuShares-2)*9999)/262142)
430+
if cpuShares <= 2 {
431+
return 1
432+
}
433+
if cpuShares >= 262144 {
434+
return 10000
435+
}
436+
l := math.Log2(float64(cpuShares))
437+
// Quadratic function which fits min, max, and default.
438+
exponent := (l*l+125*l)/612.0 - 7.0/34.0
439+
440+
return uint64(math.Ceil(math.Pow(10, exponent)))
426441
}
427442

428443
// ConvertMemorySwapToCgroupV2Value converts MemorySwap value from OCI spec

utils_test.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -535,15 +535,30 @@ func TestGetHugePageSizeImpl(t *testing.T) {
535535
}
536536

537537
func TestConvertCPUSharesToCgroupV2Value(t *testing.T) {
538+
const (
539+
sharesMin = 2
540+
sharesMax = 262144
541+
sharesDef = 1024
542+
weightMin = 1
543+
weightMax = 10000
544+
weightDef = 100
545+
unset = 0
546+
)
538547
cases := map[uint64]uint64{
539-
0: 0,
540-
2: 1,
541-
262144: 10000,
548+
unset: unset,
549+
550+
sharesMin - 1: weightMin, // Below the minimum (out of range).
551+
sharesMin: weightMin, // Minimum.
552+
sharesMin + 1: weightMin + 1, // Just above the minimum.
553+
sharesDef: weightDef, // Default.
554+
sharesMax - 1: weightMax, // Just below the maximum.
555+
sharesMax: weightMax, // Maximum.
556+
sharesMax + 1: weightMax, // Above the maximum (out of range).
542557
}
543-
for i, expected := range cases {
544-
got := ConvertCPUSharesToCgroupV2Value(i)
545-
if got != expected {
546-
t.Errorf("expected ConvertCPUSharesToCgroupV2Value(%d) to be %d, got %d", i, expected, got)
558+
for shares, want := range cases {
559+
got := ConvertCPUSharesToCgroupV2Value(shares)
560+
if got != want {
561+
t.Errorf("ConvertCPUSharesToCgroupV2Value(%d): got %d, want %d", shares, got, want)
547562
}
548563
}
549564
}

0 commit comments

Comments
 (0)