Linux

如何僅將交換空間用於緊急情況?

  • February 12, 2022

我有一台8 GB RAM 和 16 GB 交換的 Debian (Buster) 筆記型電腦。我正在執行一個很長的執行任務。這意味著我的筆記型電腦在過去六天裡一直處於開機狀態。

這樣做時,我需要定期將筆記型電腦用作筆記型電腦。這應該不是問題;長時間執行的任務受 I/O 限制,通過 USB 硬碟上的內容工作,並且不需要太多 RAM (<200 MB) 或 CPU (<4%)。

問題是當我幾個小時後回到我的筆記型電腦時,它會非常緩慢,可能需要 30 分鐘才能恢復正常。這太糟糕了,以至於崩潰監視器將它們各自的應用程序標記為已凍結(尤其是瀏覽器視窗)並且事情開始錯誤地崩潰。

查看系統監視器,大約一半使用的 2.5 GB 被轉移到交換中。我已通過刪除交換空間 ( swapoff /dev/sda8) 確認這是問題所在。如果我離開它而沒有交換空間,即使在 24 小時後它也幾乎立即恢復了生機。使用交換,前五分鐘幾乎是一塊磚,只剩下六個小時。我已經確認即使我不在,記憶體使用量也不會超過3 GB 。

我嘗試將交換性(另見:Wikipedia)減少到and100問題仍然存在。似乎在一天不活動之後,核心認為不再需要整個 GUI 並將其從 RAM 中擦除(將其交換到磁碟)。長期執行的任務是讀取龐大的文件樹並讀取每個文件。所以可能是核心被混淆了,認為記憶體會有所幫助。但是在一次掃描具有約 10 億個文件名的 2 TB USB HD 時,額外的 GB RAM 對性能沒有太大幫助。這是一款便宜的筆記型電腦,但硬碟驅動器很慢。它根本無法足夠快地將數據載入回 RAM。

**如何告訴 Linux 只在緊急情況下使用交換空間?**我不想在沒有交換的情況下執行。如果發生意外情況,並且作業系統突然需要額外的幾 GB,那麼我不希望任務被殺死,而是更願意開始使用交換。但目前,如果我啟用交換,我的筆記型電腦將無法在需要時使用。

“緊急情況”的準確定義可能有待商榷。但是要澄清我的意思:緊急情況是系統除了交換或終止程序之外別無選擇。


什麼是緊急情況?-你真的要問嗎?……我希望你永遠不會發現自己在燃燒的建築物中!

我不可能在這個問題中定義所有可能構成緊急情況的東西。但是例如,緊急情況可能是當核心被推送記憶體以致它開始使用OOM Killer殺死程序時。緊急情況不是核心認為它可以通過使用交換來提高性能。


最終編輯: 我已經接受了一個答案,它完全符合我在作業系統級別的要求。未來的讀者還應該注意提供應用級解決方案的答案。

如今進行如此巨大的交換通常是一個壞主意。當作業系統只交換了幾 GB 的記憶體進行交換時,你的系統已經爬到了死地(就像你看到的那樣)

最好與小型備份交換分區一起****使用zram。許多作業系統,如ChromeOS、Android 和各種 Linux 發行版(LubuntuFedora)多年來預設啟用 zram,尤其是對於 RAM 較少的系統。它比在 HDD 上交換要快得多,並且在這種情況下您可以清楚地感受到系統的響應能力。在 SSD 上則更少,但根據這裡的基準測試結果,即使使用預設的 lzo 算法,它似乎仍然更快。您可以更改為lz4以獲得更好的性能,但壓縮率會更低。根據官方基準,它的解碼速度比 lzo 快近 5 倍

事實上, Windows 10macOS預設也使用類似的頁面文件壓縮技術

還有,zswap雖然我沒用過。可能值得一試,比較哪個更適合您的案例

之後,另一個建議是降低那些 IO 綁定程序的優先級,並可能讓終端以更高的優先級執行,這樣即使系統處於高負載狀態,您也可以立即在其上執行命令

進一步閱讀

一種解決方法是確保記憶體 cgroup 控制器已啟用(我認為即使在半新的核心中也是預設的,否則您需要添加cgroup_enable=memory到核心命令行)。然後,您可以在具有記憶體限制的 cgroup 中執行 I/O 密集型任務,這也限制了它可以消耗的記憶體量。

如果您使用的是 systemd,您可以在單元或包含它的切片中設置+MemoryAccounting=yesMemoryHigh/MemoryMaxMemoryLimit(取決於您使用的是 cgroup v1 還是 v2)。如果它是一個切片,您可以使用它在切片systemd-run中執行程序。

來自我的一個系統的完整範例,用於執行具有記憶體限制的 Firefox。請注意,這使用 cgroups v2 並設置為我的使用者,而不是 root(v2 相對於 v1 的優點之一是將其委託給非 root 是安全的,因此 systemd 會這樣做)。

$ systemctl --user cat mozilla.slice 
# /home/anthony/.config/systemd/user/mozilla.slice
[Unit]
Description=Slice for Mozilla apps
Before=slices.target

[Slice]
MemoryAccounting=yes
MemoryHigh=5G
MemoryMax=6G

$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/firefox &
$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/thunderbird &

我發現要讓使用者工作,我必須使用切片。系統一隻需將選項放在服務文件中(或systemctl set-property在服務上使用)即可工作。

這是一個範例服務(使用 cgroup v1),請注意最後兩行。這是系統 (pid=1) 實例的一部分。

[Unit]
Description=mount S3QL filesystem
Requires=network-online.target
After=network-online.target

[Install]
WantedBy=multi-user.target

[Service]
Type=forking
User=s3ql-user
Group=s3ql-user
LimitNOFILE=20000
ExecStartPre=+/bin/sh -c 'printf "S3QL_CACHE_SIZE=%%i\n" $(stat -c "%%a*%%S*.90/1024" -f /srv/s3ql-cache/ | bc) &gt; /run/local-s3ql-env'
ExecStartPre=/usr/bin/fsck.s3ql  --cachedir /srv/s3ql-cache/fs1 --authfile /etc/s3ql-authinfo  --log none «REDACTED»
EnvironmentFile=-/run/local-s3ql-env
ExecStart=/usr/bin/mount.s3ql --keep-cache --cachedir /srv/s3ql-cache/fs1 --authfile /etc/s3ql-authinfo --cachesize ${S3QL_CACHE_SIZE} --threads 4
ExecStop=/usr/bin/umount.s3ql /mnt/S3QL/
TimeoutStopSec=2m
MemoryAccounting=yes
MemoryLimit=1G

文件位於systemd.resource-control(5).

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