Re: [PATCH v3] mm: bypass swap readahead for zswap
From: Barry Song (Xiaomi)
Date: Fri Oct 23 2026 - 17:17:03 EST
On Wed, Oct 7, 2026 at 11:39 PM Alexandre Ghiti <alex@xxxxxxxx> wrote:
>
> Commit 0bcac06f27d7 ("mm, swap: skip swapcache for swapin of synchronous
> device") made SWP_SYNCHRONOUS_IO devices (e.g. zram) skip swap readahead.
>
> zswap is the same kind of in-memory, synchronous backend as zram, not a
> swap device flagged SWP_SYNCHRONOUS_IO so it still goes through
> swapin_readahead().
>
> Here are the results from bypassing readahead for zswap too: it was
> measured with a kernel build (make -j16) in a memcg, zswap=zstd, shrinker
> off, on Sapphire Rapids and 3 iterations.
>
> 768M memcg (sustained swap thrash):
> metric mm-new + bypass delta
> build time (s) 405.0 341.7 -15.6%
> zswap-in (GB) 79.5 53.0 -33%
> zswap-out (GB) 144.8 115.6 -20%
> swap readahead (pages) 6.79M 0.45M -93%
> swap_ra hit (%) 72.1 89.9 +18pp
>
> 1G memcg (light pressure, build not memory-bound):
> metric mm-new + bypass delta
> build time (s) 177.7 176.0 ~same (no regression)
> zswap-in (GB) 10.2 7.5 -26%
> zswap-out (GB) 27.7 25.1 -9%
> swap readahead (pages) 1.07M 0.08M -93%
> swap_ra hit (%) 68.6 87.2 +19pp
>
> Similar gains were observed on an AMD EPYC 7D13 host.
>
> The gain is from no longer prefetching pages that are pointless for an
> in-memory backend: readahead inflates anon residency and thrashes the
> page cache (file pages get evicted and re-read), lengthens each fault by
> synchronously (de)compressing a cluster of neighbours, and adds
> compression traffic when those extra pages are reclaimed.
>
> Bypassing swap readahead for zswap therefore makes sense.
>
> Suggested-by: Usama Arif <usama.arif@xxxxxxxxx>
> Signed-off-by: Alexandre Ghiti <alex@xxxxxxxx>
> ---
Hi Alexandre,
One thing on my mind is that for synchronous devices, we always free
the swapcache during swap-in, thus releasing the compressed copy and
metadata as well. We could do something similar when a zswap entry
is found.
I wonder if we should do that as well. I don't have time to
investigate this further myself, but I wonder if you'd be interested
in looking into it.
mm: free swapcache on zswap hits in do_swap_page()
We already do this for zram and other synchronous devices. The same
should apply to zswap hits. Freeing the swapcache will allow the
compressed copy and metadata to be released earlier.
Suggested-by: Barry Song (Xiaomi) <baohua@xxxxxxxxxx>
diff --git a/mm/memory.c b/mm/memory.c
index 55b5a84d1016..d22c779fda93 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4711,17 +4711,18 @@ static inline bool should_try_to_free_swap(struct swap_info_struct *si,
struct folio *folio,
struct vm_area_struct *vma,
bool exclusive,
- unsigned int fault_flags)
+ unsigned int fault_flags,
+ bool sync_swap)
{
if (!folio_test_swapcache(folio))
return false;
/*
- * Always try to free swap cache for SWP_SYNCHRONOUS_IO devices. Swap
+ * Always try to free swap cache for synchronize swap entries. Swap
* cache can help save some IO or memory overhead, but these devices
* are fast, and meanwhile, swap cache pinning the slot deferring the
* release of metadata or fragmentation is a more critical issue.
*/
- if (data_race(si->flags & SWP_SYNCHRONOUS_IO))
+ if (sync_swap)
return true;
if (mem_cgroup_swap_full(folio) || (vma->vm_flags & VM_LOCKED) ||
folio_test_mlocked(folio))
@@ -4977,6 +4978,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
rmap_t rmap_flags = RMAP_NONE;
bool exclusive = false;
bool rwp_restore = false;
+ bool sync_swap = false;
softleaf_t entry;
pte_t pte;
vm_fault_t ret = 0;
@@ -5059,7 +5061,8 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
swap_update_readahead(folio, vma, vmf->address);
if (!folio) {
/* Swapin bypasses readahead for SWP_SYNCHRONOUS_IO devices and zswap */
- if (swap_entry_synchronous(si, entry))
+ sync_swap = swap_entry_synchronous(si, entry);
+ if (sync_swap)
folio = swapin_sync(entry, GFP_HIGHUSER_MOVABLE,
thp_swapin_suitable_orders(vmf) | BIT(0),
vmf, NULL, 0);
@@ -5325,7 +5328,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
* Do it after mapping, so raced page faults will likely see the folio
* in swap cache and wait on the folio lock.
*/
- if (should_try_to_free_swap(si, folio, vma, exclusive, vmf->flags))
+ if (should_try_to_free_swap(si, folio, vma, exclusive, vmf->flags, sync_swap))
folio_free_swap(folio);
folio_unlock(folio);