From nobody Mon Jun 8 18:59:01 2026 Received: from SHSQR01.spreadtrum.com (unknown [222.66.158.135]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D864B3976AD for ; Wed, 27 May 2026 08:56:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=222.66.158.135 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779872222; cv=none; b=uxdnwFhkZKvGq+T0zhMv8edSuV/q+F9vMA7lve/zU2sJuW2L6HUcyMGlgt4DCrW3HWqCfcSpZ4f64aahk0DJyGWQkgKFPYjoY1/yApcfmjStLu7khlvexnbTgKOKWOl+qQ9SSVSd5koTsoNhKJGjcWpUk8gaMKzc9zQoHBgDO4A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779872222; c=relaxed/simple; bh=LYqDE3dGO9uvlMSc/Afwer9IBtRf/dEpYfo737n7mX4=; h=From:To:Subject:Date:Message-ID:MIME-Version:Content-Type; b=tvFkSpK51KnzNe1Gsy/u/gbb3/FPur43ooNmlSdMr2oQrBnBZHxLtP8jM0XP9BHCJhdfmZiIDRaHSuwvVjf9vv8xtZR/vNQHDGvoRydHIy39WV2GlwFovX1pWBpuFOsH12g3iAPzT61nXuLdURzYh+WrXp8u3c26Hi3TSTqmjls= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=unisoc.com; spf=pass smtp.mailfrom=unisoc.com; dkim=pass (2048-bit key) header.d=unisoc.com header.i=@unisoc.com header.b=ZE5FET2t; arc=none smtp.client-ip=222.66.158.135 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=unisoc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=unisoc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=unisoc.com header.i=@unisoc.com header.b="ZE5FET2t" Received: from dlp.unisoc.com ([10.29.3.86]) by SHSQR01.spreadtrum.com with ESMTP id 64R8uY8K074539; Wed, 27 May 2026 16:56:34 +0800 (+08) (envelope-from zhaoyang.huang@unisoc.com) Received: from SHDLP.spreadtrum.com (BJMBX01.spreadtrum.com [10.0.64.7]) by dlp.unisoc.com (SkyGuard) with ESMTPS id 4gQNfx5GvDz2LpCmd; Wed, 27 May 2026 16:52:41 +0800 (CST) Received: from bj03382pcu03.spreadtrum.com (10.0.73.40) by BJMBX01.spreadtrum.com (10.0.64.7) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Wed, 27 May 2026 16:56:31 +0800 From: "zhaoyang.huang" To: Andrew Morton , Axel Rasmussen , Yuanchu Xie , Wei Xu , Johannes Weiner , David Hildenbrand , Michal Hocko , Qi Zheng , Shakeel Butt , Lorenzo Stoakes , Barry Song , , , Zhaoyang Huang , Subject: [RFC PATCH] mm/mglru: improve positive_ctrl_err for low refault samples Date: Wed, 27 May 2026 16:56:22 +0800 Message-ID: <20260527085622.1298437-1-zhaoyang.huang@unisoc.com> X-Mailer: git-send-email 2.25.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: SHCAS01.spreadtrum.com (10.0.1.201) To BJMBX01.spreadtrum.com (10.0.64.7) X-MAIL: SHSQR01.spreadtrum.com 64R8uY8K074539 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unisoc.com; s=default; t=1779872207; bh=fmzrGz9uA/PRb6gELqWbm0O/pBg7jSRrWCpQlkVQy7o=; h=From:To:Subject:Date; b=ZE5FET2tCGG2vyrY6LXbrTJBn01+UTaxoApKSgoHhbqvyIjf04d5f1PM9q3JpyQrq 3TOYy33qvYJPwCvm6pWtxS8KrUCLqAsFXDvoqTSvQqoS+YLgI8yUnu9JfsH0Jk7dvv Bs6rgpSn1uARg0E+5kRAPy3BERZ1+0vpv/ANhiNJo55/b5XuJqtsYq2pMxXzO/beVK Cw4Iwg3ks1WOrUzAIQPj+PmP8+1LUlw5oSbA1ybXLb/crTZBhOQxOI3zYTV/XBSGx6 Y0zSR5NQdA8jrlt8dCwit82co8MWiiF0a1sp19qHQdatm9zlp8rRWS/iww2yzRW9bc Gh/B/zPUtS1Lw== Content-Type: text/plain; charset="utf-8" From: Zhaoyang Huang The memory.stat under per-pid memcg & MGLRU[1] observed in android system which means current type selection by judging the refault rate almost failed since file page's refault count remains 0 which will shortcut to file by 'pv->refaulted < MIN_LRU_BATCH'. The reason could be both of small lruvec size and bypass of the file refault count when it refaulted in another memcg. Refine the MGLRU PID comparison when lruvecs lack enough refault statistics, using gain-aware fallbacks which is simply respect the swappiness and historical integral value without affecting the usual refault-rate path under sustained reclaim pressure. [1] /sys/fs/cgroup/apps/uid_10123/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D1123 steal_direct=3D32 pga= ctive=3D58 /sys/fs/cgroup/apps/uid_10136/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D2491 steal_direct=3D64 pga= ctive=3D48 /sys/fs/cgroup/apps/uid_10237/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D1355 steal_direct=3D0 pgac= tive=3D1 /sys/fs/cgroup/system/uid_1002/memory.stat: refault_anon=3D3 active_anon=3D= 1 refault_file=3D0 active_file=3D0 steal_kswapd=3D1162 steal_direct=3D4 pga= ctive=3D3987 /sys/fs/cgroup/system/uid_1027/memory.stat: refault_anon=3D1 active_anon=3D= 0 refault_file=3D0 active_file=3D0 steal_kswapd=3D1157 steal_direct=3D14 pg= active=3D1517 /sys/fs/cgroup/system/uid_1037/memory.stat: refault_anon=3D0 active_anon=3D= 0 refault_file=3D0 active_file=3D0 steal_kswapd=3D1461 steal_direct=3D0 pga= ctive=3D247 /sys/fs/cgroup/system/uid_1046/pid_1251/memory.stat: refault_anon=3D0 activ= e_anon=3D0 refault_file=3D0 active_file=3D0 steal_kswapd=3D1643 steal_direc= t=3D18 pgactive=3D2914 /sys/fs/cgroup/system/uid_1047/pid_724/memory.stat: refault_anon=3D0 active= _anon=3D0 refault_file=3D0 active_file=3D0 steal_kswapd=3D8924 steal_direct= =3D449 pgactive=3D3753 /sys/fs/cgroup/system/uid_1047/pid_789/memory.stat: refault_anon=3D0 active= _anon=3D0 refault_file=3D0 active_file=3D0 steal_kswapd=3D3864 steal_direct= =3D157 pgactive=3D3062 /sys/fs/cgroup/apps/uid_10090/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D1285 steal_direct=3D32 pga= ctive=3D36 /sys/fs/cgroup/apps/uid_10123/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D1126 steal_direct=3D32 pga= ctive=3D70 /sys/fs/cgroup/apps/uid_10136/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D2474 steal_direct=3D69 pga= ctive=3D52 /sys/fs/cgroup/apps/uid_10175/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D3264 steal_direct=3D10 pga= ctive=3D861 /sys/fs/cgroup/apps/uid_10211/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D1447 steal_direct=3D32 pga= ctive=3D21 /sys/fs/cgroup/apps/uid_10237/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D1354 steal_direct=3D0 pgac= tive=3D2 /sys/fs/cgroup/system/uid_1000/pid_471/memory.stat: refault_anon=3D0 active= _anon=3D0 refault_file=3D0 active_file=3D0 steal_kswapd=3D1296 steal_direct= =3D4 pgactive=3D65 /sys/fs/cgroup/system/uid_1002/memory.stat: refault_anon=3D18 active_anon= =3D3 refault_file=3D0 active_file=3D0 steal_kswapd=3D1286 steal_direct=3D4 = pgactive=3D3979 /sys/fs/cgroup/system/uid_1037/memory.stat: refault_anon=3D0 active_anon=3D= 0 refault_file=3D0 active_file=3D0 steal_kswapd=3D1462 steal_direct=3D0 pga= ctive=3D246 /sys/fs/cgroup/system/uid_1041/memory.stat: refault_anon=3D17 active_anon= =3D5 refault_file=3D0 active_file=3D0 steal_kswapd=3D4429 steal_direct=3D30= pgactive=3D5239 /sys/fs/cgroup/system/uid_1041/pid_820/memory.stat: refault_anon=3D12 activ= e_anon=3D0 refault_file=3D0 active_file=3D0 steal_kswapd=3D2441 steal_direc= t=3D17 pgactive=3D2034 /sys/fs/cgroup/system/uid_1041/pid_839/memory.stat: refault_anon=3D5 active= _anon=3D5 refault_file=3D0 active_file=3D0 steal_kswapd=3D1357 steal_direct= =3D10 pgactive=3D2055 /sys/fs/cgroup/system/uid_1047/pid_1166/memory.stat: refault_anon=3D0 activ= e_anon=3D0 refault_file=3D0 active_file=3D0 steal_kswapd=3D1577 steal_direc= t=3D70 pgactive=3D1130 /sys/fs/cgroup/system/uid_1047/pid_732/memory.stat: refault_anon=3D0 active= _anon=3D0 refault_file=3D0 active_file=3D0 steal_kswapd=3D7661 steal_direct= =3D115 pgactive=3D3681 /sys/fs/cgroup/system/uid_1047/pid_799/memory.stat: refault_anon=3D0 active= _anon=3D0 refault_file=3D0 active_file=3D0 steal_kswapd=3D2847 steal_direct= =3D62 pgactive=3D3573 /sys/fs/cgroup/apps/uid_10129/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D1153 steal_direct=3D18 pga= ctive=3D42 /sys/fs/cgroup/apps/uid_10136/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D2336 steal_direct=3D210 pg= active=3D49 /sys/fs/cgroup/apps/uid_10165/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D1491 steal_direct=3D43 pga= ctive=3D525 /sys/fs/cgroup/apps/uid_10175/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D2229 steal_direct=3D108 pg= active=3D863 /sys/fs/cgroup/apps/uid_10211/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D1299 steal_direct=3D163 pg= active=3D23 /sys/fs/cgroup/apps/uid_10237/memory.stat: refault_anon=3D0 active_anon=3D0= refault_file=3D0 active_file=3D0 steal_kswapd=3D1323 steal_direct=3D32 pga= ctive=3D2 /sys/fs/cgroup/system/uid_0/pid_1203/memory.stat: refault_anon=3D0 active_a= non=3D0 refault_file=3D0 active_file=3D0 steal_kswapd=3D2927 steal_direct= =3D12 pgactive=3D252 /sys/fs/cgroup/system/uid_1037/memory.stat: refault_anon=3D0 active_anon=3D= 0 refault_file=3D0 active_file=3D0 steal_kswapd=3D1359 steal_direct=3D34 pg= active=3D253 /sys/fs/cgroup/system/uid_1047/memory.stat: refault_anon=3D0 active_anon=3D= 0 refault_file=3D0 active_file=3D0 steal_kswapd=3D4269 steal_direct=3D55 pg= active=3D6308 /sys/fs/cgroup/system/uid_1047/pid_721/memory.stat: refault_anon=3D0 active= _anon=3D0 refault_file=3D0 active_file=3D0 steal_kswapd=3D2745 steal_direct= =3D44 pgactive=3D2761 Assisted-by: Cursor:GPT-5.x Signed-off-by: Zhaoyang Huang --- mm/vmscan.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index bd1b1aa12581..5fecfaa392d8 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3179,14 +3179,62 @@ static void reset_ctrl_pos(struct lruvec *lruvec, i= nt type, bool carryover) } } =20 +/* + * positive_ctrl_err() - return true if SP is hotter than PV + * + * Drives MGLRU type and tier selection in get_type_to_scan() and + * get_tier_idx(). A true return means the setpoint is hotter than the pro= cess + * variable and reclaim should favor the other type or a higher tier. + * + * With reliable refault statistics on both sides, compare refault rates. = That + * path dominates on large lruvecs under sustained memory pressure, includ= ing + * the node-level lruvec when memcg is disabled. + * + * Small memcg leaf lruvecs often lack reliable refault statistics: few pa= ges, + * infrequent reclaim, and counters reset on generation advance. Treating a + * low PV refault count as unconditional evidence that SP is hotter ignores + * swappiness and tier gain and confuses "no samples yet" with "cold". Usi= ng + * the rate comparison when only SP lacks samples skews the ratio. The + * low-sample paths below apply gain-aware fallbacks and apply defaulting = to SP + * is hotter when neither side has eviction history. + */ static bool positive_ctrl_err(struct ctrl_pos *sp, struct ctrl_pos *pv) { + unsigned long pv_ref =3D pv->refaulted; + /* Used by the rate comparison (SP only) and the total fallback (both). */ + unsigned long sp_total =3D sp->total + MIN_LRU_BATCH; + unsigned long pv_total =3D pv->total + MIN_LRU_BATCH; + + /* Both sides: compare refault rates. */ + if (sp->refaulted >=3D MIN_LRU_BATCH && pv->refaulted >=3D MIN_LRU_BATCH) + goto compare_rates; + + /* + * SP only: PV refault count is not statistically meaningful; treat PV + * refaults as zero and use the rate comparison (yields SP hotter). + */ + if (sp->refaulted >=3D MIN_LRU_BATCH) { + pv_ref =3D 0; + goto compare_rates; + } + + /* PV only: trust PV refault signal; SP is not hotter. */ + if (pv->refaulted >=3D MIN_LRU_BATCH) + return false; + + /* Neither side has eviction history, pv is colder */ + if (!sp->total && !pv->total) + return true; + + /* Neither side has enough refaults: compare gain-weighted totals. */ + return sp->gain * pv_total <=3D pv->gain * sp_total; + +compare_rates: /* - * Return true if the PV has a limited number of refaults or a lower - * refaulted/total than the SP. + * Rate comparison with margin on SP total and refault only; PV total is + * not padded so a meaningful PV refault rate is preserved when sampled. */ - return pv->refaulted < MIN_LRU_BATCH || - pv->refaulted * (sp->total + MIN_LRU_BATCH) * sp->gain <=3D + return pv_ref * sp_total * sp->gain <=3D (sp->refaulted + 1) * pv->total * pv->gain; } =20 --=20 2.25.1