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