All of lore.kernel.org
 help / color / mirror / Atom feed
From: Usama Arif <usama.arif@linux.dev>
To: Johannes Weiner <hannes@cmpxchg.org>
Cc: Usama Arif <usama.arif@linux.dev>,
	Andrew Morton <akpm@linux-foundation.org>,
	david@kernel.org, ljs@kernel.org, liam@infradead.org,
	vbabka@kernel.org, rppt@kernel.org, surenb@google.com,
	mhocko@suse.com, kasong@tencent.com, qi.zheng@linux.dev,
	shakeel.butt@linux.dev, axelrasmussen@google.com,
	yuanchu@google.com, weixugc@google.com, chrisl@kernel.org,
	nphamcs@gmail.com, baoquan.he@linux.dev, youngjun.park@lge.com,
	roman.gushchin@linux.dev, muchun.song@linux.dev,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	cgroups@vger.kernel.org, rientjes@google.com,
	kernel-team@meta.com
Subject: Re: [PATCH v3 2/2] mm/vmscan: reduce lru_lock contention via vmstat-derived scan-balance cost
Date: Mon, 20 Jul 2026 10:02:44 -0700	[thread overview]
Message-ID: <20260720170245.939058-1-usama.arif@linux.dev> (raw)
In-Reply-To: <20260717210808.GI6843@cmpxchg.org>

On Fri, 17 Jul 2026 23:08:08 +0200 Johannes Weiner <hannes@cmpxchg.org> wrote:

> On Fri, Jul 17, 2026 at 06:57:32AM -0700, Usama Arif wrote:
> > @@ -2303,12 +2301,63 @@ static void prepare_scan_control(pg_data_t *pgdat, struct scan_control *sc)
> >  	mem_cgroup_flush_stats_ratelimited(sc->target_mem_cgroup);
> >  
> >  	/*
> > -	 * Determine the scan balance between anon and file LRUs.
> > +	 * Determine the scan balance between anon and file LRUs from per-LRU
> > +	 * vmstat counters. The raw cost per side is:
> > +	 *
> > +	 *	PGROTATE	   - reclaim-driven rotations, bumped from both
> > +	 *			     shrink_inactive_list and shrink_active_list
> > +	 *			     (CPU work).
> > +	 *	NR_VMSCAN_WRITE    - reclaim-driven anon pageout IO.
> > +	 *	WORKINGSET_RESTORE - refaults of previously-workingset pages.
> > +	 *
> > +	 * The two IO terms are weighted by SWAP_CLUSTER_MAX to reflect the
> > +	 * higher cost of an IO over a rotation.
> > +	 *
> > +	 * Reads are lock-free per-cpu sum collations, rstat-aggregated up
> > +	 * the memcg hierarchy by mem_cgroup_flush_stats_ratelimited() above.
> > +	 * Use lruvec_page_state_monotonic() so the unsigned subtraction
> > +	 * `now - prev_cost[f]` yields the correct delta across a signed-long
> > +	 * wraparound of the underlying counter (a real hazard on 32-bit that
> > +	 * the clamp in lruvec_page_state() would otherwise turn into a huge
> > +	 * spurious delta).
> > +	 *
> > +	 * The delta against prev_cost is folded into cost_accum, which is
> > +	 * halved on both sides until their sum is within lrusize/4.
> > +	 * cost_lock serialises concurrent reclaimers in the same memcg+node.
> 
> IMO that's a lot of describing what the code does. Why not stick
> closer to the original comments?
> 
> >  	 */
> > -	spin_lock_irq(&target_lruvec->lru_lock);
> > -	sc->anon_cost = target_lruvec->anon_cost;
> > -	sc->file_cost = target_lruvec->file_cost;
> > -	spin_unlock_irq(&target_lruvec->lru_lock);
> > +	spin_lock(&target_lruvec->cost_lock);
> > +	for (int f = 0; f <= 1; f++) {
> > +		unsigned long now, delta;
> > +
> > +		now = lruvec_page_state_monotonic(target_lruvec, PGROTATE_ANON + f) +
> > +		      lruvec_page_state_monotonic(target_lruvec,
> > +						  WORKINGSET_RESTORE_BASE + f) *
> > +				SWAP_CLUSTER_MAX;
> > +		if (f == WORKINGSET_ANON)
> > +			now += lruvec_page_state_monotonic(target_lruvec,
> > +							   NR_VMSCAN_WRITE) *
> > +				SWAP_CLUSTER_MAX;
> 
> It's hard to prove overflow behavior is correct. I would keep the
> delta extraction dead simple, then do the weight math on the delta.
> 
> > +		delta = now - target_lruvec->prev_cost[f];
> > +		target_lruvec->prev_cost[f] = now;
> > +		target_lruvec->cost_accum[f] += delta;
> > +	}
> > +	unsigned long lrusize =
> > +		lruvec_page_state(target_lruvec, NR_INACTIVE_ANON) +
> > +		lruvec_page_state(target_lruvec, NR_ACTIVE_ANON) +
> > +		lruvec_page_state(target_lruvec, NR_INACTIVE_FILE) +
> > +		lruvec_page_state(target_lruvec, NR_ACTIVE_FILE);
> > +	unsigned long cost_limit = lrusize / 4;
> > +
> > +	while (target_lruvec->cost_accum[WORKINGSET_ANON] > cost_limit ||
> > +	       target_lruvec->cost_accum[WORKINGSET_FILE] > cost_limit ||
> > +	       target_lruvec->cost_accum[WORKINGSET_ANON] +
> > +	       target_lruvec->cost_accum[WORKINGSET_FILE] > cost_limit) {
> > +		target_lruvec->cost_accum[WORKINGSET_ANON] /= 2;
> > +		target_lruvec->cost_accum[WORKINGSET_FILE] /= 2;
> 
> Why do you need to check them individually? Between reclaim cycles,
> there are no scans->rotations. And I don't see how you could get
> refault events several times the size of the LRU, let alone in excess
> of ULONG_MAX.
> 
> > +	}
> > +	sc->anon_cost = target_lruvec->cost_accum[WORKINGSET_ANON];
> > +	sc->file_cost = target_lruvec->cost_accum[WORKINGSET_FILE];
> > +	spin_unlock(&target_lruvec->cost_lock);
> 
> I realize these long descriptor names make it hard, but I think this
> can be cleaned up a bit and written in a more idiomatic way.
> 

Thanks for the prototype and the above reivew comments!

I integrated all of them and sent them as v4.

And best part of it is, sashiko is happy as well now with v4 lol


      reply	other threads:[~2026-07-20 17:03 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-17 13:57 [PATCH v3 0/2] mm/vmscan: reduce lru_lock contention via vmstat-derived scan-balance cost Usama Arif
2026-07-17 13:57 ` [PATCH v3 1/2] mm/vmstat, mm/memcontrol: add _monotonic vmstat readers Usama Arif
2026-07-17 13:57 ` [PATCH v3 2/2] mm/vmscan: reduce lru_lock contention via vmstat-derived scan-balance cost Usama Arif
2026-07-17 21:08   ` Johannes Weiner
2026-07-20 17:02     ` Usama Arif [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260720170245.939058-1-usama.arif@linux.dev \
    --to=usama.arif@linux.dev \
    --cc=akpm@linux-foundation.org \
    --cc=axelrasmussen@google.com \
    --cc=baoquan.he@linux.dev \
    --cc=cgroups@vger.kernel.org \
    --cc=chrisl@kernel.org \
    --cc=david@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=kasong@tencent.com \
    --cc=kernel-team@meta.com \
    --cc=liam@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=mhocko@suse.com \
    --cc=muchun.song@linux.dev \
    --cc=nphamcs@gmail.com \
    --cc=qi.zheng@linux.dev \
    --cc=rientjes@google.com \
    --cc=roman.gushchin@linux.dev \
    --cc=rppt@kernel.org \
    --cc=shakeel.butt@linux.dev \
    --cc=surenb@google.com \
    --cc=vbabka@kernel.org \
    --cc=weixugc@google.com \
    --cc=youngjun.park@lge.com \
    --cc=yuanchu@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.