Skip to content

Commit 4d03b87

Browse files
committed
cgroup: improve conversion from shares to weight
The OCI CPU shares (range [2-262144]) to cgroup v2 `cpu.weight` (range [1-10000]) conversion formula has been updated to use a quadratic function so that min, max and default values match. Closes: #1721 Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
1 parent a84e656 commit 4d03b87

File tree

5 files changed

+38
-11
lines changed

5 files changed

+38
-11
lines changed

configure.ac

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@ fi
321321

322322
AC_SEARCH_LIBS([argp_parse], [argp], [], [AC_MSG_ERROR([*** argp functions not found - install libargp or argp_standalone])])
323323

324+
AC_SEARCH_LIBS([log2], [m], [], [AC_MSG_ERROR([*** -lm not found])])
325+
324326
AM_CONDITIONAL([PYTHON_BINDINGS], [test "x$with_python_bindings" = "xyes"])
325327
AM_CONDITIONAL([LUA_BINDINGS], [test "x$with_lua_bindings" = "xyes"])
326328
AM_CONDITIONAL([CRIU_SUPPORT], [test "x$have_criu" = "xyes"])

crun.1

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,10 @@ allbox;
836836
l l l l
837837
l l l l .
838838
\fBOCI (x)\fP \fBcgroup 2 value (y)\fP \fBconversion\fP \fBcomment\fP
839-
shares cpu.weight y = (1 + ((x - 2) * 9999) / 262142) T{
839+
shares cpu.weight T{
840+
y=10^((log2(x)^2 + 125 * log2(x)) / 612.0 - 7.0 / 34.0)
841+
T}
842+
T{
840843
convert from [2-262144] to [1-10000]
841844
T}
842845
period cpu.max y = x T{

crun.1.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -702,11 +702,11 @@ they are converted when needed from the cgroup v1 configuration.
702702

703703
## CPU controller
704704

705-
| OCI (x) | cgroup 2 value (y) | conversion | comment |
706-
|---|---|---|---|
707-
| shares | cpu.weight | y = (1 + ((x - 2) \* 9999) / 262142) | convert from [2-262144] to [1-10000]|
708-
| period | cpu.max | y = x| period and quota are written together|
709-
| quota | cpu.max | y = x| period and quota are written together|
705+
| OCI (x) | cgroup 2 value (y) | conversion | comment |
706+
|---------|--------------------|---------------------------------------------------------|---------------------------------------|
707+
| shares | cpu.weight | y=10^((log2(x)^2 + 125 * log2(x)) / 612.0 - 7.0 / 34.0) | convert from [2-262144] to [1-10000] |
708+
| period | cpu.max | y = x | period and quota are written together |
709+
| quota | cpu.max | y = x | period and quota are written together |
710710

711711
## blkio controller
712712

src/libcrun/cgroup-internal.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
#include "container.h"
2222
#include "utils.h"
2323

24+
#include <stdint.h>
25+
#include <math.h>
26+
2427
enum
2528
{
2629
CGROUP_MEMORY = 1 << 0,
@@ -76,8 +79,26 @@ int libcrun_cgroup_pause_unpause_path (const char *cgroup_path, const bool pause
7679
static inline uint64_t
7780
convert_shares_to_weight (uint64_t shares)
7881
{
79-
/* convert linearly from 2-262144 to 1-10000. */
80-
return (1 + ((shares - 2) * 9999) / 262142);
82+
/* Converts OCI shares (2-262144) to cgroup v2 cpu.weight (1-10000).
83+
This uses the same formula as systemd, differing from the earlier linear conversion.
84+
The result is clamped to ensure it falls within the valid weight range. */
85+
86+
double l, exponent;
87+
88+
/* The value of 0 means "unset". */
89+
if (shares == 0)
90+
return 0;
91+
if (shares < 2)
92+
return 1;
93+
if (shares > 262144)
94+
return 10000;
95+
96+
l = log2 ((double) shares);
97+
98+
/* Quadratic function which fits min, max, and default. */
99+
exponent = (l * l + 125 * l) / 612.0 - 7.0 / 34.0;
100+
101+
return (uint64_t) ceil (pow (10, exponent));
81102
}
82103

83104
int initialize_cpuset_subsystem (const char *path, libcrun_error_t *err);

tests/test_resources.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,13 +291,14 @@ def test_resources_cpu_weight_systemd():
291291
sys.stderr.write("found wrong CPUWeight for the systemd scope\n")
292292
return 1
293293

294-
run_crun_command(['update', '--cpu-share', '4321', cid])
294+
cpu_shares = 4321
295+
run_crun_command(['update', '--cpu-share', str(cpu_shares), cid])
295296
# this is the expected cpu weight after the conversion from the CPUShares
296-
expected_weight = "165"
297+
expected_weight = str(max(1, min(10000, cpu_shares * 100 // 1024)))
297298

298299
out = run_crun_command(["exec", cid, "/init", "cat", "/sys/fs/cgroup/cpu.weight"])
299300
if expected_weight not in out:
300-
sys.stderr.write("found wrong CPUWeight %s for the container cgroup\n" % out)
301+
sys.stderr.write("found wrong CPUWeight %s instead of %s for the container cgroup\n" % (out, expected_weight))
301302
return -1
302303

303304
out = subprocess.check_output(['systemctl', 'show','-PCPUWeight', scope ], close_fds=False).decode().strip()

0 commit comments

Comments
 (0)