如何僅將交換空間用於緊急情況?
我有一台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)減少到and的值,
10
但0
問題仍然存在。似乎在一天不活動之後,核心認為不再需要整個 GUI 並將其從 RAM 中擦除(將其交換到磁碟)。長期執行的任務是讀取龐大的文件樹並讀取每個文件。所以可能是核心被混淆了,認為記憶體會有所幫助。但是在一次掃描具有約 10 億個文件名的 2 TB USB HD 時,額外的 GB RAM 對性能沒有太大幫助。這是一款便宜的筆記型電腦,但硬碟驅動器很慢。它根本無法足夠快地將數據載入回 RAM。**如何告訴 Linux 只在緊急情況下使用交換空間?**我不想在沒有交換的情況下執行。如果發生意外情況,並且作業系統突然需要額外的幾 GB,那麼我不希望任務被殺死,而是更願意開始使用交換。但目前,如果我啟用交換,我的筆記型電腦將無法在需要時使用。
“緊急情況”的準確定義可能有待商榷。但是要澄清我的意思:緊急情況是系統除了交換或終止程序之外別無選擇。
什麼是緊急情況?-你真的要問嗎?……我希望你永遠不會發現自己在燃燒的建築物中!
我不可能在這個問題中定義所有可能構成緊急情況的東西。但是例如,緊急情況可能是當核心被推送記憶體以致它開始使用OOM Killer殺死程序時。緊急情況不是核心認為它可以通過使用交換來提高性能。
最終編輯: 我已經接受了一個答案,它完全符合我在作業系統級別的要求。未來的讀者還應該注意提供應用級解決方案的答案。
如今進行如此巨大的交換通常是一個壞主意。當作業系統只交換了幾 GB 的記憶體進行交換時,你的系統已經爬到了死地(就像你看到的那樣)
最好與小型備份交換分區一起****使用
zram
。許多作業系統,如ChromeOS、Android 和各種 Linux 發行版(Lubuntu、Fedora)多年來預設啟用 zram,尤其是對於 RAM 較少的系統。它比在 HDD 上交換要快得多,並且在這種情況下您可以清楚地感受到系統的響應能力。在 SSD 上則更少,但根據這裡的基準測試結果,即使使用預設的 lzo 算法,它似乎仍然更快。您可以更改為lz4以獲得更好的性能,但壓縮率會更低。根據官方基準,它的解碼速度比 lzo 快近 5 倍事實上, Windows 10和macOS預設也使用類似的頁面文件壓縮技術
還有,
zswap
雖然我沒用過。可能值得一試,比較哪個更適合您的案例之後,另一個建議是降低那些 IO 綁定程序的優先級,並可能讓終端以更高的優先級執行,這樣即使系統處於高負載狀態,您也可以立即在其上執行命令
進一步閱讀
一種解決方法是確保記憶體 cgroup 控制器已啟用(我認為即使在半新的核心中也是預設的,否則您需要添加
cgroup_enable=memory
到核心命令行)。然後,您可以在具有記憶體限制的 cgroup 中執行 I/O 密集型任務,這也限制了它可以消耗的記憶體量。如果您使用的是 systemd,您可以在單元或包含它的切片中設置
+MemoryAccounting=yes
和MemoryHigh
/MemoryMax
或MemoryLimit
(取決於您使用的是 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) > /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)
.