1 | % SPDX-License-Identifier: GPL-2.0 |
2 | % |
3 | % run as: octave-cli memcg_protection.m |
4 | % |
5 | % This script simulates reclaim protection behavior on a single level of memcg |
6 | % hierarchy to illustrate how overcommitted protection spreads among siblings |
7 | % (as it depends also on their current consumption). |
8 | % |
9 | % Simulation assumes siblings consumed the initial amount of memory (w/out |
10 | % reclaim) and then the reclaim starts, all memory is reclaimable, i.e. treated |
11 | % same. It simulates only non-low reclaim and assumes all memory.min = 0. |
12 | % |
13 | % Input configurations |
14 | % -------------------- |
15 | % E number parent effective protection |
16 | % n vector nominal protection of siblings set at the given level (memory.low) |
17 | % c vector current consumption -,,- (memory.current) |
18 | |
19 | % example from testcase (values in GB) |
20 | E = 50 / 1024; |
21 | n = [75 25 0 500 ] / 1024; |
22 | c = [50 50 50 0] / 1024; |
23 | |
24 | % Reclaim parameters |
25 | % ------------------ |
26 | |
27 | % Minimal reclaim amount (GB) |
28 | cluster = 32*4 / 2**20; |
29 | |
30 | % Reclaim coefficient (think as 0.5^sc->priority) |
31 | alpha = .1 |
32 | |
33 | % Simulation parameters |
34 | % --------------------- |
35 | epsilon = 1e-7; |
36 | timeout = 1000; |
37 | |
38 | % Simulation loop |
39 | % --------------- |
40 | |
41 | ch = []; |
42 | eh = []; |
43 | rh = []; |
44 | |
45 | for t = 1:timeout |
46 | % low_usage |
47 | u = min(c, n); |
48 | siblings = sum(u); |
49 | |
50 | % effective_protection() |
51 | protected = min(n, c); % start with nominal |
52 | e = protected * min(1, E / siblings); % normalize overcommit |
53 | |
54 | % recursive protection |
55 | unclaimed = max(0, E - siblings); |
56 | parent_overuse = sum(c) - siblings; |
57 | if (unclaimed > 0 && parent_overuse > 0) |
58 | overuse = max(0, c - protected); |
59 | e += unclaimed * (overuse / parent_overuse); |
60 | endif |
61 | |
62 | % get_scan_count() |
63 | r = alpha * c; % assume all memory is in a single LRU list |
64 | |
65 | % commit 1bc63fb1272b ("mm, memcg: make scan aggression always exclude protection" ) |
66 | sz = max(e, c); |
67 | r .*= (1 - (e+epsilon) ./ (sz+epsilon)); |
68 | |
69 | % uncomment to debug prints |
70 | % e, c, r |
71 | |
72 | % nothing to reclaim, reached equilibrium |
73 | if max(r) < epsilon |
74 | break; |
75 | endif |
76 | |
77 | % SWAP_CLUSTER_MAX roundup |
78 | r = max(r, (r > epsilon) .* cluster); |
79 | % XXX here I do parallel reclaim of all siblings |
80 | % in reality reclaim is serialized and each sibling recalculates own residual |
81 | c = max(c - r, 0); |
82 | |
83 | ch = [ch ; c]; |
84 | eh = [eh ; e]; |
85 | rh = [rh ; r]; |
86 | endfor |
87 | |
88 | t |
89 | c, e |
90 | |