[Deepin-Kernel-SIG] [linux 6.18.y] [Upstream] [PATCH v5 mm-new 0/2] mm/swapfile.c: select swap devices of default priority round robin#1994
Conversation
mainline inclusion from mainline-v6.19-rc1 category: performance Patch series "mm/swapfile.c: select swap devices of default priority round robin", v5. Currently, on system with multiple swap devices, swap allocation will select one swap device according to priority. The swap device with the highest priority will be chosen to allocate firstly. People can specify a priority from 0 to 32767 when swapon a swap device, or the system will set it from -2 then downwards by default. Meanwhile, on NUMA system, the swap device with node_id will be considered first on that NUMA node of the node_id. In the current code, an array of plist, swap_avail_heads[nid], is used to organize swap devices on each NUMA node. For each NUMA node, there is a plist organizing all swap devices. The 'prio' value in the plist is the negated value of the device's priority due to plist being sorted from low to high. The swap device owning one node_id will be promoted to the front position on that NUMA node, then other swap devices are put in order of their default priority. E.g I got a system with 8 NUMA nodes, and I setup 4 zram partition as swap devices. Current behaviour: their priorities will be(note that -1 is skipped): NAME TYPE SIZE USED PRIO /dev/zram0 partition 16G 0B -2 /dev/zram1 partition 16G 0B -3 /dev/zram2 partition 16G 0B -4 /dev/zram3 partition 16G 0B -5 And their positions in the 8 swap_avail_lists[nid] will be: swap_avail_lists[0]: /* node 0's available swap device list */ zram0 -> zram1 -> zram2 -> zram3 prio:1 prio:3 prio:4 prio:5 swap_avali_lists[1]: /* node 1's available swap device list */ zram1 -> zram0 -> zram2 -> zram3 prio:1 prio:2 prio:4 prio:5 swap_avail_lists[2]: /* node 2's available swap device list */ zram2 -> zram0 -> zram1 -> zram3 prio:1 prio:2 prio:3 prio:5 swap_avail_lists[3]: /* node 3's available swap device list */ zram3 -> zram0 -> zram1 -> zram2 prio:1 prio:2 prio:3 prio:4 swap_avail_lists[4-7]: /* node 4,5,6,7's available swap device list */ zram0 -> zram1 -> zram2 -> zram3 prio:2 prio:3 prio:4 prio:5 The adjustment for swap device with node_id intended to decrease the pressure of lock contention for one swap device by taking different swap device on different node. The adjustment was introduced in commit a2468cc ("swap: choose swap device according to numa node"). However, the adjustment is a little coarse-grained. On the node, the swap device sharing the node's id will always be selected firstly by node's CPUs until exhausted, then next one. And on other nodes where no swap device shares its node id, swap device with priority '-2' will be selected firstly until exhausted, then next with priority '-3'. This is the swapon output during the process high pressure vm-scability test is being taken. It's clearly showing zram0 is heavily exploited until exhausted. =================================== [root@hp-dl385g10-03 ~]# swapon NAME TYPE SIZE USED PRIO /dev/zram0 partition 16G 15.7G -2 /dev/zram1 partition 16G 3.4G -3 /dev/zram2 partition 16G 3.4G -4 /dev/zram3 partition 16G 2.6G -5 The node based strategy on selecting swap device is much better then the old way one by one selecting swap device. However it is still unreasonable because swap devices are assumed to have similar accessing speed if no priority is specified when swapon. It's unfair and doesn't make sense just because one swap device is swapped on firstly, its priority will be higher than the one swapped on later. So in this patchset, change is made to select the swap device round robin if default priority. In code, the plist array swap_avail_heads[nid] is replaced with a plist swap_avail_head which reverts commit a2468cc. Meanwhile, on top of the revert, further change is taken to make any device w/o specified priority get the same default priority '-1'. Surely, swap device with specified priority are always put foremost, this is not impacted. If you care about their different accessing speed, then use 'swapon -p xx' to deploy priority for your swap devices. New behaviour: swap_avail_list: /* one global available swap device list */ zram0 -> zram1 -> zram2 -> zram3 prio:1 prio:1 prio:1 prio:1 This is the swapon output during the process high pressure vm-scability being taken, all is selected round robin: ======================================= [root@hp-dl385g10-03 linux]# swapon NAME TYPE SIZE USED PRIO /dev/zram0 partition 16G 12.6G -1 /dev/zram1 partition 16G 12.6G -1 /dev/zram2 partition 16G 12.6G -1 /dev/zram3 partition 16G 12.6G -1 With the change, we can see about 18% efficiency promotion as below: vm-scability test: ================== Test with: usemem --init-time -O -y -x -n 31 2G (4G memcg, zram as swap) Before: After: System time: 637.92 s 526.74 s (lower is better) Sum Throughput: 3546.56 MB/s 4207.56 MB/s (higher is better) Single process Throughput: 114.40 MB/s 135.72 MB/s (higher is better) free latency: 10138455.99 us 6810119.01 us (low is better) This patch (of 2): This reverts commit a2468cc ("swap: choose swap device according to numa node"). After this patch, the behaviour will change back to pre-commit a2468cc. Means the priority will be set from -1 then downwards by default, and when swapping, it will exhault swap device one by one according to priority from high to low. This is preparation work for later change. [root@hp-dl385g10-03 ~]# swapon NAME TYPE SIZE USED PRIO /dev/zram0 partition 16G 16G -1 /dev/zram1 partition 16G 966.2M -2 /dev/zram2 partition 16G 0B -3 /dev/zram3 partition 16G 0B -4 Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Baoquan He <[email protected]> Suggested-by: Chris Li <[email protected]> Acked-by: Chris Li <[email protected]> Acked-by: Nhat Pham <[email protected]> Reviewed-by: Kairui Song <[email protected]> Cc: Barry Song <[email protected]> Cc: Kemeng Shi <[email protected]> Signed-off-by: Andrew Morton <[email protected]> (cherry picked from commit 8e689f8) Signed-off-by: Wentao Guan <[email protected]>
mainline inclusion from mainline-v6.19-rc1 category: performance Swap devices are assumed to have similar accessing speed when swapon if no priority is specified. It's unfair and doesn't make sense just because one swap device is swapped on firstly, its priority will be higher than the one swapped on later. Here, set all swap devicess to have priority '-1' by default. With this change, swap device with default priority will be selected round robin when swapping out. This can improve the swapping efficiency a lot among multiple swap devices with default priority. Below are swapon output during the processes when high pressure vm-scability test is being taken: 1) This is pre-commit a2468cc, swap device is selectd one by one by priority from high to low when one swap device is exhausted: ------------------------------------ [root@hp-dl385g10-03 ~]# swapon NAME TYPE SIZE USED PRIO /dev/zram0 partition 16G 16G -1 /dev/zram1 partition 16G 966.2M -2 /dev/zram2 partition 16G 0B -3 /dev/zram3 partition 16G 0B -4 2) This is behaviour with commit a2468cc, on node, swap device sharing the same node id is selected firstly until exhausted; while on node no swap device sharing the node id it selects the one with highest priority until exhaustd: ------------------------------------ [root@hp-dl385g10-03 ~]# swapon NAME TYPE SIZE USED PRIO /dev/zram0 partition 16G 15.7G -2 /dev/zram1 partition 16G 3.4G -3 /dev/zram2 partition 16G 3.4G -4 /dev/zram3 partition 16G 2.6G -5 3) After this patch applied, swap devices with default priority are selectd round robin: ------------------------------------ [root@hp-dl385g10-03 block]# swapon NAME TYPE SIZE USED PRIO /dev/zram0 partition 16G 6.6G -1 /dev/zram1 partition 16G 6.6G -1 /dev/zram2 partition 16G 6.6G -1 /dev/zram3 partition 16G 6.6G -1 With the change, about 18% efficiency promotion relative to node based way as below. (Surely, the pre-commit a2468cc way is the worst.) vm-scability test: ================== Test with: usemem --init-time -O -y -x -n 31 2G (4G memcg, zram as swap) one by one: node based: round robin: System time: 1087.38 s 637.92 s 526.74 s (lower is better) Sum Throughput: 2036.55 MB/s 3546.56 MB/s 4207.56 MB/s (higher is better) Single process Throughput: 65.69 MB/s 114.40 MB/s 135.72 MB/s (high is better) free latency: 15769409.48 us 10138455.99 us 6810119.01 us(lower is better) Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Baoquan He <[email protected]> Suggested-by: Chris Li <[email protected]> Acked-by: Chris Li <[email protected]> Acked-by: Nhat Pham <[email protected]> Cc: Barry Song <[email protected]> Cc: Kairui Song <[email protected]> Cc: Kemeng Shi <[email protected]> Signed-off-by: Andrew Morton <[email protected]> (cherry picked from commit 52f37ef) Signed-off-by: Wentao Guan <[email protected]>
mainline inclusion from mainline-v6.19-rc1 category: bugfix swap_alloc_slow() was checking `si->avail_list` instead of `next->avail_list` when verifying if the next swap device is still in the list, which could cause unnecessary restarts during allocation. Link: https://lkml.kernel.org/r/[email protected] Fixes: 8e689f8 ("mm/swap: do not choose swap device according to numa node") Signed-off-by: Youngjun Park <[email protected]> Acked-by: Kairui Song <[email protected]> Reviewed-by: Baoquan He <[email protected]> Cc: Barry Song <[email protected]> Cc: Chris Li <[email protected]> Cc: Kemeng Shi <[email protected]> Cc: Nhat Pham <[email protected]> Signed-off-by: Andrew Morton <[email protected]> (cherry picked from commit c230719) Signed-off-by: Wentao Guan <[email protected]>
Reviewer's guide (collapsed on small PRs)Reviewer's GuideThis PR reverts NUMA-aware per-node swap device selection and replaces it with a single global priority-ordered list, then standardizes the default swap priority to -1 so that multiple devices with default priority are selected round robin, while still honoring explicitly configured priorities. Sequence diagram for global round-robin swap device selectionsequenceDiagram
participant Process
participant mm as mm_swapfile
participant head as swap_avail_head
participant si as swap_info_struct
Process->>mm: swapon(specialfile, swap_flags)
mm->>mm: alloc_swap_info()
mm->>mm: setup_swap_info(si, prio)
note over mm: prio = DEF_SWAP_PRIO unless SWAP_FLAG_PREFER
mm->>mm: enable_swap_info(si, prio, ...)
mm->>mm: add_to_avail_list(si, true)
mm->>head: plist_add(si.avail_list, swap_avail_head)
Process->>mm: folio_alloc_swap(...)
mm->>mm: swap_alloc_slow(entry, order)
mm->>head: plist_for_each_entry_safe(si, next, swap_avail_head, avail_list)
mm->>head: plist_requeue(si.avail_list, swap_avail_head)
mm->>mm: cluster_alloc_swap_entry(si, order, SWAP_HAS_CACHE)
mm-->>Process: swap entry allocated round robin across default-priority devices
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- The removal of per-node swap_avail_heads and swap_node() changes NUMA-aware behavior significantly; consider adding a brief code comment near swap_alloc_slow explaining that the allocation is now intentionally NUMA-unaware to avoid future confusion or accidental reintroduction.
- Since least_priority and the auto-adjustment of negative priorities on swapoff are gone, review mixed-priority scenarios to ensure the new DEF_SWAP_PRIO handling still matches intended ordering when devices with explicit priorities coexist with default-priority ones, and clarify that behavior in the priority assignment code.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The removal of per-node swap_avail_heads and swap_node() changes NUMA-aware behavior significantly; consider adding a brief code comment near swap_alloc_slow explaining that the allocation is now intentionally NUMA-unaware to avoid future confusion or accidental reintroduction.
- Since least_priority and the auto-adjustment of negative priorities on swapoff are gone, review mixed-priority scenarios to ensure the new DEF_SWAP_PRIO handling still matches intended ordering when devices with explicit priorities coexist with default-priority ones, and clarify that behavior in the priority assignment code.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Pull request overview
This PR updates the swap device selection policy to stop using NUMA-node-specific available lists and instead perform round-robin selection among swap devices that have the default (auto) priority, while keeping explicitly assigned priorities ordered ahead as before.
Changes:
- Replace per-NUMA-node
swap_avail_heads[]tracking with a single globalswap_avail_headlist. - Assign a uniform default swap priority (
-1) so default-priority devices are selected round-robin rather than “first swapon wins”. - Remove NUMA swap selection documentation and its index entry.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| mm/swapfile.c | Switches swap availability tracking to a single global plist and adjusts swap allocation/rotation accordingly. |
| include/linux/swap.h | Simplifies swap_info_struct by replacing the per-node avail_lists[] array with a single avail_list node. |
| Documentation/admin-guide/mm/swap_numa.rst | Removes documentation for the NUMA-based swap selection behavior. |
| Documentation/admin-guide/mm/index.rst | Drops the swap_numa entry from the MM documentation index. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| shrinker_debugfs | ||
| slab | ||
| soft-dirty | ||
| swap_numa | ||
| transhuge | ||
| userfaultfd |
Link: https://lore.kernel.org/all/[email protected]/T/#u
Currently, on system with multiple swap devices, swap allocation will
select one swap device according to priority. The swap device with the
highest priority will be chosen to allocate firstly.
People can specify a priority from 0 to 32767 when swapon a swap device,
or the system will set it from -2 then downwards by default. Meanwhile,
on NUMA system, the swap device with node_id will be considered first
on that NUMA node of the node_id.
In the current code, an array of plist, swap_avail_heads[nid], is used
to organize swap devices on each NUMA node. For each NUMA node, there
is a plist organizing all swap devices. The 'prio' value in the plist
is the negated value of the device's priority due to plist being sorted
from low to high. The swap device owning one node_id will be promoted to
the front position on that NUMA node, then other swap devices are put in
order of their default priority.
E.g I got a system with 8 NUMA nodes, and I setup 4 zram partition as
swap devices.
Current behaviour:
their priorities will be(note that -1 is skipped):
NAME TYPE SIZE USED PRIO
/dev/zram0 partition 16G 0B -2
/dev/zram1 partition 16G 0B -3
/dev/zram2 partition 16G 0B -4
/dev/zram3 partition 16G 0B -5
And their positions in the 8 swap_avail_lists[nid] will be:
swap_avail_lists[0]: /* node 0's available swap device list /
zram0 -> zram1 -> zram2 -> zram3
prio:1 prio:3 prio:4 prio:5
swap_avali_lists[1]: / node 1's available swap device list /
zram1 -> zram0 -> zram2 -> zram3
prio:1 prio:2 prio:4 prio:5
swap_avail_lists[2]: / node 2's available swap device list /
zram2 -> zram0 -> zram1 -> zram3
prio:1 prio:2 prio:3 prio:5
swap_avail_lists[3]: / node 3's available swap device list /
zram3 -> zram0 -> zram1 -> zram2
prio:1 prio:2 prio:3 prio:4
swap_avail_lists[4-7]: / node 4,5,6,7's available swap device list */
zram0 -> zram1 -> zram2 -> zram3
prio:2 prio:3 prio:4 prio:5
The adjustment for swap device with node_id intended to decrease the
pressure of lock contention for one swap device by taking different
swap device on different node. The adjustment was introduced in commit
a2468cc ("swap: choose swap device according to numa node").
However, the adjustment is a little coarse-grained. On the node, the swap
device sharing the node's id will always be selected firstly by node's CPUs
until exhausted, then next one. And on other nodes where no swap device
shares its node id, swap device with priority '-2' will be selected firstly
until exhausted, then next with priority '-3'.
This is the swapon output during the process high pressure vm-scability
test is being taken. It's clearly showing zram0 is heavily exploited until
exhausted.
===================================
[root@hp-dl385g10-03 ~]# swapon
NAME TYPE SIZE USED PRIO
/dev/zram0 partition 16G 15.7G -2
/dev/zram1 partition 16G 3.4G -3
/dev/zram2 partition 16G 3.4G -4
/dev/zram3 partition 16G 2.6G -5
The node based strategy on selecting swap device is much better then the
old way one by one selecting swap device. However it is still unreasonable
because swap devices are assumed to have similar accessing speed if no
priority is specified when swapon. It's unfair and doesn't make sense just
because one swap device is swapped on firstly, its priority will be higher
than the one swapped on later.
So in this patchset, change is made to select the swap device round robin
if default priority. In code, the plist array swap_avail_heads[nid] is replaced
with a plist swap_avail_head which reverts commit a2468cc. Meanwhile,
on top of the revert, further change is taken to make any device w/o
specified priority get the same default priority '-1'. Surely, swap device
with specified priority are always put foremost, this is not impacted. If
you care about their different accessing speed, then use 'swapon -p xx' to
deploy priority for your swap devices.
New behaviour:
swap_avail_list: /* one global available swap device list */
zram0 -> zram1 -> zram2 -> zram3
prio:1 prio:1 prio:1 prio:1
This is the swapon output during the process high pressure vm-scability
being taken, all is selected round robin:
[root@hp-dl385g10-03 linux]# swapon
NAME TYPE SIZE USED PRIO
/dev/zram0 partition 16G 12.6G -1
/dev/zram1 partition 16G 12.6G -1
/dev/zram2 partition 16G 12.6G -1
/dev/zram3 partition 16G 12.6G -1
With the change, we can see about 18% efficiency promotion as below:
vm-scability test:
Test with:
usemem --init-time -O -y -x -n 31 2G (4G memcg, zram as swap)
Before: After:
System time: 637.92 s 526.74 s (lower is better)
Sum Throughput: 3546.56 MB/s 4207.56 MB/s (higher is better)
Single process Throughput: 114.40 MB/s 135.72 MB/s (higher is better)
free latency: 10138455.99 us 6810119.01 us (low is better)
Changelog:
v4->v5:
v3->v4:
v2->v3:
a2468cc, the 2nd is making change to set default priority as -1
for all swap devices which makes swapping out select swap device round
robin. This eases patch reviewing which is suggested by Chris, thanks.
v2 patch. clean that up.
v1->v2:
Thanks a lot for careful reviewing from Chris, YoungJun and Kairui.
Baoquan He (2):
mm/swap: do not choose swap device according to numa node
mm/swap: select swap device with default priority round robin
Documentation/admin-guide/mm/index.rst | 1 -
Documentation/admin-guide/mm/swap_numa.rst | 78 ---------------
include/linux/swap.h | 11 +--
mm/swapfile.c | 106 ++++-----------------
4 files changed, 17 insertions(+), 179 deletions(-)
delete mode 100644 Documentation/admin-guide/mm/swap_numa.rst
--
2.41.0
Summary by Sourcery
Revert NUMA-based swap device selection and introduce round-robin allocation among swap devices with the default priority, simplifying swap availability tracking to a single global list.
New Features:
Enhancements:
Documentation: