Re: [PATCH v1 2/2] mm/memory: add anonymous mTHP folios to deferred split list
Johannes Weiner <[email protected]> Mon, 3 Aug 2026 20:48:44 -0400
| Newsgroups | org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
Hello Barry, On Tue, Aug 04, 2026 at 05:20:00AM +0800, Barry Song wrote: > On Mon, Aug 3, 2026 at 10:45 PM Johannes Weiner <[email protected]> wrote: > > On Sat, Aug 01, 2026 at 03:33:42PM +0800, Barry Song wrote: > > > On Fri, Jul 31, 2026 at 11:04 PM Johannes Weiner <[email protected]> wrote: > > > > 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. ^^^ > > > My understanding is that adding smaller folios to the deferred split > > > list is not the right approach. We could end up with a very large list > > > where we cannot distinguish partially unmapped folios from fully mapped > > > ones. For example, the deferred split list could contain 100 fully mapped > > > folios but only a single partially mapped folio. > > > Moreover, for smaller large folios, the number of zero subpages > > > is likely to be small and short-lived. > > > > > > However, this is probably fine for larger large folios, since it is > > > unlikely to significantly increase the size of the deferred split > > > list. In other words, the deferred split list should remain manageable. > > > For the same reason, larger large folios may not benefit much from the > > > LRU cache either. > > > > > > So if we have some mechanism to prevent users from doing things that > > > are not beneficial, such as adding smaller large folios to the list, it > > > seems reasonable to me. > > > > Just to clarify, we're on the same page, right? I was proposing a > > mechanism to do just that. > > For example, with smaller folios, the distribution might look > something like this: > > Smaller large folios > > +------------------------------------------------------------+ > | F | F | F | F | F | F | F | F | F | F | F | F | F | P | Z | > +------------------------------------------------------------+ > > F: Fully mapped (dominant) > P: Partially mapped (rare) > Z: Zero subpages mapped (rare) > > So it doesn't make much sense to add them to the list, because we > would rarely find P, and even the few Z entries we do find would > soon be filled with non-zero data anyway. > > For larger folios, the list becomes much shorter. As folio size > increases, they are more likely to contain zero-filled subpages: > > Larger large folios: > > +------------------------------------------------------------+ > | F | P | Z | F | P | Z | P | F | Z | F | P | Z | F | P | Z | > +------------------------------------------------------------+ > > F, P and Z become much more evenly distributed. > > So if the folio is large enough, this seems acceptable. I know a > sysctl knob may not be well received, as it adds to the user's > configuration burden. Perhaps we could just hard-code a > sufficiently large value instead? for example, > > #define LARGE_FOLIO_ZERO_SCAN_MIN_SIZE SZ_2M > > if (folio_size(folio) >= LARGE_FOLIO_ZERO_SCAN_MIN_SIZE) > deferred_split_folio(folio, false); > > If, someday, people find that 1 MiB also helps, they can provide > data to support it. I am very confused. Did you not see my proposal above? Why not 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();