Skip to content

Commit ec74ad9

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 073b9b8 commit ec74ad9

File tree

5 files changed

+56
-11
lines changed

5 files changed

+56
-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_DEFINE([HAVE_LOG2], 1, [Define if log2 is available])], [])
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
@@ -846,7 +846,10 @@ allbox;
846846
l l l l
847847
l l l l .
848848
\fBOCI (x)\fP \fBcgroup 2 value (y)\fP \fBconversion\fP \fBcomment\fP
849-
shares cpu.weight y = (1 + ((x - 2) * 9999) / 262142) T{
849+
shares cpu.weight T{
850+
y=10^((log2(x)^2 + 125 * log2(x)) / 612.0 - 7.0 / 34.0)
851+
T}
852+
T{
850853
convert from [2-262144] to [1-10000]
851854
T}
852855
period cpu.max y = x T{

crun.1.md

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

713713
## CPU controller
714714

715-
| OCI (x) | cgroup 2 value (y) | conversion | comment |
716-
|---|---|---|---|
717-
| shares | cpu.weight | y = (1 + ((x - 2) \* 9999) / 262142) | convert from [2-262144] to [1-10000]|
718-
| period | cpu.max | y = x| period and quota are written together|
719-
| quota | cpu.max | y = x| period and quota are written together|
715+
| OCI (x) | cgroup 2 value (y) | conversion | comment |
716+
|---------|--------------------|---------------------------------------------------------|---------------------------------------|
717+
| shares | cpu.weight | y=10^((log2(x)^2 + 125 * log2(x)) / 612.0 - 7.0 / 34.0) | convert from [2-262144] to [1-10000] |
718+
| period | cpu.max | y = x | period and quota are written together |
719+
| quota | cpu.max | y = x | period and quota are written together |
720720

721721
## blkio controller
722722

src/libcrun/cgroup-internal.h

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

24+
#include <stdint.h>
25+
#ifdef HAVE_LOG2
26+
# include <math.h>
27+
#endif
28+
2429
enum
2530
{
2631
CGROUP_MEMORY = 1 << 0,
@@ -76,8 +81,42 @@ int libcrun_cgroup_pause_unpause_path (const char *cgroup_path, const bool pause
7681
static inline uint64_t
7782
convert_shares_to_weight (uint64_t shares)
7883
{
79-
/* convert linearly from 2-262144 to 1-10000. */
80-
return (1 + ((shares - 2) * 9999) / 262142);
84+
/* The value of 0 means "unset". */
85+
if (shares == 0)
86+
return 0;
87+
if (shares < 2)
88+
return 1;
89+
if (shares > 262144)
90+
return 10000;
91+
92+
#ifdef HAVE_LOG2
93+
double l, exponent;
94+
95+
l = log2 ((double) shares);
96+
97+
/* Quadratic function which fits min, max, and default. */
98+
exponent = (l * l + 125 * l) / 612.0 - 7.0 / 34.0;
99+
100+
return (uint64_t) ceil (pow (10, exponent));
101+
#else
102+
/* Simplified version if the math library is not present. */
103+
104+
/* Split the interval in two segments making sure to map the minimum, default, and maximum value. */
105+
uint64_t weight;
106+
107+
if (shares < 1024)
108+
{
109+
/* Segment 1: Shares 2 -> 1024 maps to Weight 1 -> 100. */
110+
weight = (99ULL * shares + 824ULL) / 1022ULL;
111+
}
112+
else
113+
{
114+
/* Segment 2: Shares 1024 -> 262144 maps to Weight 100 -> 10000. */
115+
weight = (9900ULL * shares + 15974400ULL) / 261120ULL;
116+
}
117+
118+
return weight;
119+
#endif
81120
}
82121

83122
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)