Linux

當我有千兆字節的可用記憶體時,頂部顯示“swout”(交換)。為什麼?

  • February 15, 2021

當我有千兆字節的可用記憶體時,為什麼atop顯示我正在換出超過 20,000 個頁面 - 超過 80 兆字節?

我沒有註意到這有性能問題。我只是想藉此機會增加我的知識:-)。

atop每十秒刷新一次。每次刷新都會顯示自上次刷新以來的活動。

MEM | tot     7.7G | free    3.7G | cache 608.3M | buff   19.1M | slab  264.6M |
SWP | tot     2.0G | free    1.4G |              | vmcom  13.4G | vmlim   5.8G |
PAG | scan  167264 | steal 109112 | stall      0 | swin       0 | swout  23834 |

                               "swout" is non-zero and coloured in red  ^

核心記憶體資訊:

$ head -n 5 /proc/meminfo
MemTotal:        8042664 kB
MemFree:         3563088 kB
MemAvailable:    3922092 kB
Buffers:           20484 kB
Cached:           775308 kB

核心版本:

$ uname -r
5.0.16-200.fc29.x86_64

  1. 目前尚不清楚這是否會受到影響vm.swappiness。該設置平衡了記憶體回收與交換。但是有大量可用記憶體,那麼為什麼我們首先需要回收任何記憶體呢?
  2. 如您所見,這是一個小型系統。它不使用 NUMA。我簽入了/proc/zoneinfo,我只有一個節點,“節點 0”。所以這不是由 NUMA 引起的
  3. 相關問答中提到了“機會性交換”、“當系統無事可做時”、“如果以後出現記憶體短缺時可能會提供好處”等想法。我認為這些想法並不可信,因為它們與核心文件相矛盾。請參閱 Linux 是否執行“機會交換”,還是一個神話?
  4. 使用systemd.resources功能對 RAM 的使用沒有設置限制。即,我認為所有systemd單位的 RAM 使用限制都設置為“無窮大”。
$ systemctl show '*' | \
   grep -E '(Memory|Swap).*(Max|Limit|High)' | \
   grep -v infinity
$
  1. 編輯:我懷疑這與透明大頁面有關。我注意到虛擬機使用透明的大頁面來有效地分配客戶記憶體。它們是我係統上唯一使用大頁面的使用者程序。

有一個類似的問題:如果空閒記憶體遠遠超過 pages_high watermark,kswapd 可以處於活動狀態嗎?它詢問的是 RHEL 6,它為所有應用程序啟用了大頁面。

我不確定如何重現此結果。

它發生在啟動VM時。我使用 libvirt 來執行虛擬機。預設情況下,VM 磁碟讀取使用主機頁面記憶體進行記憶體。(記憶體模式:“Hypervisor default”表示“Writeback”)。

我嘗試停止 VM、FADVISE_DONTNEED映像文件,然後重試。但同樣的事情並沒有發生。

然後我用不同的虛擬機再次嘗試,它發生了短暫的。我抓到了vmstat。我認為atop“swout”顯示了一個不同的、更高的數字,但我沒有捕捉到它。

$ vmstat 10
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
0  0 770168 5034300  28024 936256    0    2    21    86   60  101 22  9 68  1  0
0  0 770168 5033852  28048 935904    0    0     0     8  372  633  1  1 97  0  0
1  0 770168 4974048  28252 948152    3    0  1137   194 1859 2559 11  7 79  3  0
0  1 770168 4557968  28308 1037512    0    0  8974    45 3595 6218 16  6 57 21  0
6  3 770168 4317800  28324 1111408    0    0  7200   609 6820 6793 12  5 38 44  0
0  4 770168 4125100  28348 1182624    0    0  6900   269 5054 3674 74  3  8 15  0
0  5 770168 3898200  27840 1259768    2    0  9421   630 4694 5465 11  6 11 71  0
1  3 770168 3760316  27672 1300540    0    0  9294   897 3308 4135  5  4 28 63  0
0  1 770168 3531332  27032 1356236    0    0 10532   155 3140 4949  8  5 63 25  0
0  0 783772 3381556  27032 1320296    0 1390  7320  4210 4450 5112 17  5 43 35  0
0  0 783772 3446284  27056 1335116    0    0   239   441  995 1782  4  2 92  2  0
0  0 783772 3459688  27076 1335372    0    0     3   410  728 1037  2  2 95  1  0

我還檢查了 VM 上的 cgroup 記憶體限制,以防 libvirt 繞過systemd並錯誤地對自身造成交換:

$ cd /sys/fs/cgroup/memory/machine.slice/machine-qemu\x2d5\x2ddebian9.scope
$ find -type d  # there were no sub-directories here
$ grep -H . *limit_in_bytes
memory.kmem.limit_in_bytes:9223372036854771712
memory.kmem.tcp.limit_in_bytes:9223372036854771712
memory.limit_in_bytes:9223372036854771712
memory.memsw.limit_in_bytes:9223372036854771712
memory.soft_limit_in_bytes:9223372036854771712
$ cd ../..
$ find -name "*limit_in_bytes" -exec grep -H -v 9223372036854771712 \{\} \;
$

我正在思考一個類似的問題——你看到了我關於 kswapd 和區域水印的文章——而在我的情況下(也可能在你的情況下)的答案是記憶體碎片。

當記憶體碎片足夠多時,高階分配將失敗,這(取決於許多其他因素)將導致直接回收,或者將喚醒 kswapd,後者將嘗試進行區域回收/壓縮。你可以在我的文章中找到一些額外的細節。

處理此類問題時可能會引起注意的另一件事是記憶體分區。即你可能有足夠的記憶體(它甚至可能包含足夠的連續塊),但它可能僅限於 DMA32(如果你在 64 位架構上)*。*有些人傾向於將 DMA32 視為“小”(可能是因為他們習慣於 32 位思維),但 4GB 並不是真正的“小”。

您有兩種方法可以確定您的情況發生了什麼。一種是分析統計數據——您可以設置作業以定期對 /proc/buddyinfo、/proc/zoneinfo、/proc/vmstat 等進行快照,並嘗試從您所看到的內容中理解。

如果你讓它工作,另一種方法更直接和可靠:你需要擷取導致交換事件的程式碼路徑,你可以使用核心檢測到的跟踪點來做到這一點(特別是,有許多 vmscan 事件)。

但是讓它工作可能具有挑戰性,因為低級儀器並不總是按照它應該開箱即用的方式工作。在我的例子中,我們不得不花費一些時間來設置 ftrace 基礎設施,但最終卻發現我們需要的 function_graph 探針由於某種原因無法正常工作。我們嘗試的下一個工具是 perf,但第一次嘗試也沒有成功。但是,當您最終設法擷取感興趣的事件時,它們可能會比任何全域計數器更快地引導您找到答案。

最好的問候,尼古拉

引用自:https://unix.stackexchange.com/questions/521152