The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Baoquan He <baoquan.he@linux.dev>
To: linux-mm@kvack.org
Cc: akpm@linux-foundation.org, hannes@cmpxchg.org, yosry@kernel.org,
	nphamcs@gmail.com, chengming.zhou@linux.dev, chrisl@kernel.org,
	kasong@tencent.com, shikemeng@huaweicloud.com, baohua@kernel.org,
	youngjun.park@lge.com, linux-kernel@vger.kernel.org,
	Baoquan He <baoquan.he@linux.dev>
Subject: [RFC PATCH 0/7] mm: store zswap entries in swap table (Pointer entry)
Date: Tue,  7 Jul 2026 15:31:57 +0800	[thread overview]
Message-ID: <20260707073215.72183-1-baoquan.he@linux.dev> (raw)

Currently zswap uses a per-swap-device xarray to map swap offsets to
zswap_entry pointers. This introduces an additional tree walk on every
zswap entry access.

This series replaces the xarray with a "Pointer" entry type stored
directly in the swap cluster table. The new swp_tb_t variant embeds
a zswap_entry pointer plus a entry count, eliminating the xarray and
its lookup overhead entirely.

Design overview
---------------
A swap table slot can now be one of five types:

  NULL:    |---------------- 0 ---------------|
  Shadow:  |SWAP_COUNT|Z|---- SHADOW_VAL ---|1|
  PFN:     |SWAP_COUNT|Z|------ PFN -------|10|
  Pointer: |----------- Pointer ----------|100|
  Bad:     |------------- 1 -------------|1000|

When zswap compresses a page, it saves the original swap table entry
(PFN or Shadow) in zswap_entry->swp_tb_val, then writes the Pointer
entry into the swap table.  The swap count and flags remain accessible
via helper functions that read them from swp_tb_val.

The zswap_entry is threaded through the swapin call chain via a new
void **zentry parameter, so zswap_load() receives it directly instead
of doing an xarray lookup.

Performance
-----------
[~]# free -h
               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       155Mi       3.4Gi       656Ki       315Mi       3.7Gi
Swap:          4.0Gi        54Mi       3.9Gi

Scalability benchmark: 'usemem -O -y -x -n 1 5G', 10 runs under cgroup
MemoryMax=2G MemorySwapMax=3G.  zswap enabled with zstd compressor.

  Kernel A: cfb8731f5396 (xarray-based lookup, baseline)
  Kernel B: (Pointer entry)

5G test — the gap widens significantly as swap pressure grows:

     Metric           xarray(A)       Pointer(B)
    --------------------------------------------------
    Avg throughput      709,556 KB/s    792,681 KB/s  (+11.7%)
    Avg free time       167,994 µs     132,896 µs   (-20.9%)

  Free time trend across 10 rounds at 5G:

    Pointer: 126→124→126→126→124→129→138→145→142→148  (gradual, +17%)
    xarray:  136→139→136→160→162→161→159→230→219→178  (collapse, +31%)

  xarray degrades sharply in the later rounds (last 3 avg free time
  209 ms vs Pointer's 145 ms, 1.44× worse) as the radix tree
  insertion/deletion cost grows non-linearly under sustained swap
  churn.  Pointer entry avoids this entirely by looking up entries
  directly in the swap cluster table, which is already hot in cache.

Baoquan He (7):
  mm/swap_table: add Pointer type support for zswap entry storage
  mm/zswap: add swp_tb_val to zswap_entry and Pointer accessor helpers
  mm/swap_state: do zswap conversion in __swap_cache_do_del_folio
  mm/zswap, mm/swap_state: handle Pointer entries in add_folio path
  mm/swapfile: handle Pointer entries in count/dup/put paths
  mm/zswap, mm/swap_state: migrate zswap to use swap_table for entry
    indexing
  mm/zswap, mm/swap_state: replace xarray indexing with swap table
    lookups

 include/linux/zswap.h |   4 +-
 mm/page_io.c          |   4 +-
 mm/swap.h             |  52 +++++-
 mm/swap_state.c       | 117 +++++++++++---
 mm/swap_table.h       |  35 ++++-
 mm/swapfile.c         | 107 ++++++++++---
 mm/zswap.c            | 358 +++++++++++++++++++++++++++++-------------
 7 files changed, 508 insertions(+), 169 deletions(-)

-- 
2.54.0


             reply	other threads:[~2026-07-07  7:32 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-07  7:31 Baoquan He [this message]
2026-07-07  7:31 ` [RFC PATCH 1/7] mm/swap_table: add Pointer type support for zswap entry storage Baoquan He
2026-07-07  7:31 ` [RFC PATCH 2/7] mm/zswap: add swp_tb_val to zswap_entry and Pointer accessor helpers Baoquan He
2026-07-07  7:32 ` [RFC PATCH 3/7] mm/swap_state: do zswap conversion in __swap_cache_do_del_folio Baoquan He
2026-07-07  7:32 ` [RFC PATCH 4/7] mm/zswap, mm/swap_state: handle Pointer entries in add_folio path Baoquan He
2026-07-07  7:32 ` [RFC PATCH 5/7] mm/swapfile: handle Pointer entries in count/dup/put paths Baoquan He
2026-07-07  7:32 ` [RFC PATCH 6/7] mm/zswap, mm/swap_state: migrate zswap to use swap_table for entry indexing Baoquan He
2026-07-07  7:32 ` [RFC PATCH 7/7] mm/zswap, mm/swap_state: replace xarray indexing with swap table lookups Baoquan He

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=20260707073215.72183-1-baoquan.he@linux.dev \
    --to=baoquan.he@linux.dev \
    --cc=akpm@linux-foundation.org \
    --cc=baohua@kernel.org \
    --cc=chengming.zhou@linux.dev \
    --cc=chrisl@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=kasong@tencent.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=nphamcs@gmail.com \
    --cc=shikemeng@huaweicloud.com \
    --cc=yosry@kernel.org \
    --cc=youngjun.park@lge.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