當我有千兆字節的可用記憶體時,頂部顯示“swout”(交換)。為什麼?
當我有千兆字節的可用記憶體時,為什麼
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
- 目前尚不清楚這是否會受到影響
vm.swappiness
。該設置平衡了記憶體回收與交換。但是有大量可用記憶體,那麼為什麼我們首先需要回收任何記憶體呢?- 如您所見,這是一個小型系統。它不使用 NUMA。我簽入了
/proc/zoneinfo
,我只有一個節點,“節點 0”。所以這不是由 NUMA 引起的。- 相關問答中提到了“機會性交換”、“當系統無事可做時”、“如果以後出現記憶體短缺時可能會提供好處”等想法。我認為這些想法並不可信,因為它們與核心文件相矛盾。請參閱 Linux 是否執行“機會交換”,還是一個神話?
- 使用
systemd.resources
功能對 RAM 的使用沒有設置限制。即,我認為所有systemd
單位的 RAM 使用限制都設置為“無窮大”。$ systemctl show '*' | \ grep -E '(Memory|Swap).*(Max|Limit|High)' | \ grep -v infinity $
- 編輯:我懷疑這與透明大頁面有關。我注意到虛擬機使用透明的大頁面來有效地分配客戶記憶體。它們是我係統上唯一使用大頁面的使用者程序。
有一個類似的問題:如果空閒記憶體遠遠超過 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,但第一次嘗試也沒有成功。但是,當您最終設法擷取感興趣的事件時,它們可能會比任何全域計數器更快地引導您找到答案。
最好的問候,尼古拉