Commit | Line | Data |
---|---|---|
f10b6e9a MK |
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 |