From: Johannes Weiner <hannes@cmpxchg.org>
To: Barry Song <baohua@kernel.org>
Cc: "David Hildenbrand (Arm)" <david@kernel.org>,
Joanne Koong <joannelkoong@gmail.com>,
akpm@linux-foundation.org, ljs@kernel.org, usama.arif@linux.dev,
alex@ghiti.fr, ziy@nvidia.com, baolin.wang@linux.alibaba.com,
liam@infradead.org, npache@redhat.com, ryan.roberts@arm.com,
dev.jain@arm.com, lance.yang@linux.dev, vbabka@kernel.org,
rppt@kernel.org, surenb@google.com, mhocko@suse.com,
willy@infradead.org, linux-mm@kvack.org
Subject: Re: [PATCH v1 2/2] mm/memory: add anonymous mTHP folios to deferred split list
Date: Fri, 31 Jul 2026 11:04:04 -0400 [thread overview]
Message-ID: <amy5ZKC2Kc7RX94Q@cmpxchg.org> (raw)
In-Reply-To: <CAGsJ_4yWAUcXmVr7Oe1V42szqi2Od-0MhDBspNKURZcBnub9+Q@mail.gmail.com>
On Fri, Jul 31, 2026 at 05:31:20AM +0800, Barry Song wrote:
> On Thu, Jul 30, 2026 at 11:38 PM Johannes Weiner <hannes@cmpxchg.org> wrote:
> >
> > On Thu, Jul 30, 2026 at 03:46:25PM +0200, David Hildenbrand (Arm) wrote:
> > > On 7/29/26 17:04, Johannes Weiner wrote:
> > > > (2) With a mix of basepages and THPs, there could indeed be a lot of
> > > > basepages ahead of underused THPs. That means swapping before
> > > > getting to space that is much cheaper to reclaim.
> > > >
> > > > The current setup isn't perfect in that regard, as the shrinker
> > > > runs simultaneously as the LRU. But it's making guaranteed forward
> > > > progress through the THPs, even as the first LRU pages are scanned.
> > >
> > > The shrinker would obviously remain and scan the list for candidates.
> >
> > That's slightly different from what I had pictured. But I don't think
> > it changes my arguments much.
> >
> > > We might want to remember how man / if any such entries we have on
> > > the list.
> >
> > Right. The question is how does the shrinker actually find them:
> >
> > > > (3) The anon LRU has folio lifetime, but the splitqueue is one-shot:
> > > > we scan each THP once, and then it's either split and dropped, or
> > > > found full and dropped. That THP never needs to be revisited. The
> > > > queue actually empties as the workload establishes itself.
> > > >
> > > > The anon LRU ~ splitqueue argument is only true around startup.
> > > >
> > > > If we used the anon LRU, we'd need per-page state to avoid repeat
> > > > underused checks. And we need external state to not scan the anon
> > > > LRU at all if there are no new THPs (and no swap). And if that's
> > > > just a counter for "new, not yet scanned THPs", a single fault
> > > > will cause you to walk the entire anon LRU before you get to it.
> > >
> > > Remembering "not yet scanned" through a pageflag (for large folios) is indeed
> > > very easy.
> > >
> > > I don't quite understand the "a single fault", can you elaborate?
> >
> > Let's say you have a 1TB host with 800G anon populated.
> >
> > The oldest folios on the list might be THP. The newest ones might
> > be. You could have a mix of basepages and THPs. The ordering
> > constantly changes as the folios are aged, rotated, reclaimed.
> >
> > How can it find a handful of unscanned THPs in an ocean of folios?
> > Even if you mark the folio state, that's hundreds of millions of
> > entries whose state you have to check in the worst case?
> >
> > The lru lock is one of the most congested MM locks on large
> > machines. *Maybe* you can do it locklessly.
> >
> > Maybe you can add thresholds where you don't scan if there aren't
> > "that many" new THPs just yet. That means magic numbers and reduced
> > predictability.
> >
> > Maybe you can be clever and scan from the head of the inactive list
> > where (most) new folios start. You still need to skip over basepages
> > that faulted after. Skip over the referenced pages that have been
> > rotated around concurrently. That could mitigate some common cases,
> > but not the worst case.
> >
> > The search pool stays enormous for the entire runtime of the
> > workload. It never gets better, never converges. It continues to
> > include every other irrelevant anon page, and every THP that you've
> > previously scanned already. A single new THP fault and the search
> > problem starts over.
> >
> > I just don't see how that's algorithmically sound.
> >
> > > > So I think reusing the anon LRU is flawed. It's fundamentally
> > > > different needles in fundamentally different haystacks.
> > > >
> > > > If we can agree on that, then the lock contention problem has a
> > > > different scope as well: it's a simple optimization issue, not a
> > > > fundamental data structure arrangement issue.
> > >
> > > I don't agree yet :) But maybe I am missing something important.
> > >
> > > Note that the "simple optimization issue" is not so simple once you
> > > realize what kind of a pain the batched LRU already creates us when it
> > > comes to predicting the number of expected folio references.
> > >
> > > It's a pain I don't want to extend to other areas.
> >
> > Since we already need to do it for the LRU pages anyway, isn't it a "+
> > in_deferred_cache(folio) extension to existing refcount checks?
> >
> > I don't want to sound dismissive at all. It's a problem. However,
> >
> > - it seems way more tractable than the shared list,
> > - nobody has produced hard data to show that either is justified.
> >
> > > > If I understand you correctly, the concern is that people will enable
> > > > all manner of mTHP orders, and 99% of the anon faults, including all
> > > > the order-3, order-4 pagelets, will go through the list_lru lock on
> > > > fault, with no batching.
> > >
> > > Yes. See Barry's LRU cache change I linked as reply to Usama who is looking for
> > > example at a system that mostly just uses order-2 anon folios.
> >
> > I took a look, but I just see a microbenchmark. That doesn't seem
> > enough to make a proper cost-benefit analysis on the complexity that's
> > being proposed - whether that's a shared list design, or a splitqueue
> > cache.
>
> Hi Johannes,
>
> Sorry for being lazy and not including the necessary background in the
> RFC cover letter.
>
> The background is that our goal is to enable only order-2 (16 KiB)
> mTHPs on Android. Based on our long-term experience with large folios
> on Android-like systems, we believe this offers the best tradeoff
> between the benefits of mTHPs and their costs, including increased
> memory footprint, fragmentation, compaction overhead, and internal
> memory waste.
Thanks for laying this out!
Again, IMO the microbenchmark was plenty justification for using the
LRU cache, no worries. That's a straight-forward plumbing change. I
was just saying we should probably know more before pursuing a much
more complex direction for the THP shrinker. So thank you!
> Specifically:
>
> 1. We obtain most of the performance benefits of mTHPs, including, for
> example, a 4x reduction in page faults, faster memory reclamation at a
> larger granularity, and making it easier to allocate higher-order
> dma-bufs. While larger mTHPs can further reduce page faults, they also
> increase memory footprint, which is a significant concern on
> memory-constrained Android devices.
>
> 2. We minimize the internal memory waste associated with mTHPs.
This is kind of tangential, but I'm curious if you would have
experimented with larger folios AND the THP shrinker?
In Meta, 2M thp=always without the shrinker would also not have been
tolerable. It OOMed immediately on a large number of services. The
shrinker *is* what allowed us to use such large folios to begin with,
without the internal memory waste problem.
> 3. We can use a lightweight compaction strategy that only needs to
> satisfy order-2 allocations, keeping the compaction overhead low.
>
> 4. Combined with large-block compression and decompression, 16 KiB
> pages provide more than 80% of the CPU savings and compression-ratio
> improvements achievable with larger folios[1].
That's very interesting, thanks for filling in the details. How this
jives with compaction and compression units is clever.
> For such a system, I don't think adding these folios to the deferred
> list provides much benefit. Since the mTHPs are relatively small, there
> are unlikely to be many zero subpages. Even if there are, they are
> likely to be short-lived and will quickly become non-zero again as the
> workload continues.
That's good to know as well.
> But I can see the benefit in Usama's case with 2 MB mTHPs. For larger
> folios, adding them to the deferred list could be helpful.
>
> [1] https://lore.kernel.org/linux-mm/20241121222521.83458-1-21cnbao@gmail.com/
Here is an idea: the THP shrinker will not consider anything unused
that has <= max_ptes_none zero pages. See thp_underused(). Joanne was
proposing to scale this knob down relative to the folio size for mTHP
shrinking. What if instead we kept the meaning absolute?
The knob is an expression of how much waste the user is willing to
tolerate per folio. If the folio order in question couldn't possibly
have that much waste in the first place, we don't have to queue it?
Something like this:
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 2bccb0a53a0a..1670e9869bd3 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -4364,6 +4364,9 @@ void deferred_split_folio(struct folio *folio, bool partially_mapped)
if (!partially_mapped && !split_underused_thp)
return;
+ if (!partially_mapped && folio_nr_pages(folio) <= khugepaged_max_ptes_none)
+ return;
+
/*
* Exclude swapcache: originally to avoid a corrupt deferred split
* queue. Nowadays that is fully prevented by __memcg1_swapout();
The setting defaults to the PMD-1, so out of the box we wouldn't queue
any new orders. It would allow that 2MB on 64k ARM usecase, without
jeopardizing smaller mTHP usecases like Barry's.
Thoughts?
next prev parent reply other threads:[~2026-07-31 15:04 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-07 20:17 [PATCH v1 0/2] mm: split underused anonymous mTHP folios Joanne Koong
2026-07-07 20:17 ` [PATCH v1 1/2] mm/huge_memory: extend thp_underused() to " Joanne Koong
2026-07-08 4:03 ` Joanne Koong
2026-07-07 20:17 ` [PATCH v1 2/2] mm/memory: add anonymous mTHP folios to deferred split list Joanne Koong
2026-07-08 7:56 ` David Hildenbrand (Arm)
2026-07-08 9:58 ` Usama Arif
2026-07-29 12:36 ` David Hildenbrand (Arm)
2026-07-29 13:43 ` Usama Arif
2026-07-29 14:02 ` Usama Arif
2026-07-30 13:28 ` David Hildenbrand (Arm)
2026-07-08 17:52 ` Joanne Koong
2026-07-29 12:38 ` David Hildenbrand (Arm)
2026-07-29 15:04 ` Johannes Weiner
2026-07-30 13:46 ` David Hildenbrand (Arm)
2026-07-30 15:37 ` Johannes Weiner
2026-07-30 21:31 ` Barry Song
2026-07-30 23:32 ` Barry Song
2026-07-31 15:04 ` Johannes Weiner [this message]
2026-07-08 7:46 ` [PATCH v1 0/2] mm: split underused anonymous mTHP folios David Hildenbrand (Arm)
2026-07-08 18:19 ` Joanne Koong
2026-07-30 13:52 ` David Hildenbrand (Arm)
2026-07-30 23:10 ` Joanne Koong
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=amy5ZKC2Kc7RX94Q@cmpxchg.org \
--to=hannes@cmpxchg.org \
--cc=akpm@linux-foundation.org \
--cc=alex@ghiti.fr \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=david@kernel.org \
--cc=dev.jain@arm.com \
--cc=joannelkoong@gmail.com \
--cc=lance.yang@linux.dev \
--cc=liam@infradead.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@suse.com \
--cc=npache@redhat.com \
--cc=rppt@kernel.org \
--cc=ryan.roberts@arm.com \
--cc=surenb@google.com \
--cc=usama.arif@linux.dev \
--cc=vbabka@kernel.org \
--cc=willy@infradead.org \
--cc=ziy@nvidia.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox