zram,舊稱為 compcache,是一個用於在內存中創建壓縮的塊設備的 Linux 內核模塊,即帶實時磁碟壓縮的內存檔。通過 zram 創建的塊設備可以用作 swap 或是內存檔。zram 有兩個常見的應用場景,一個是儲存臨時文件(/tmp
),另一個是用作 swap。早期 zram 只有後一個功能,也是它原名 「compcache」 (compressed cache) 的由來。
作為 swap 的使用
在最開始,創建出的 zram 塊設備並不會預留或使用任何內存。僅當有文件需要被或者想要被交換出內存時,它們才會被壓縮並移入 zram 塊設備。因此,zram 塊設備將會根據需要動態地增長或收縮。
即使保守估計 zstd 只能達到 1:2 壓縮比(實際中壓縮比通常為 1:3),zram 也能提供在內存中存儲比不進行內存壓縮更多內容的優勢。
- 在配置 zram 時設置的 zram 大小指代可存儲的最大未壓縮數據量,不是指壓縮後的數據大小。只要內存中的壓縮後數據量小於系統物理內存容量,你甚至可以將 zram 大小配置為等於或大於系統物理內存容量。
- 假如相關的 zswap 內核功能為啟用狀態,它將阻礙 zram 的有效使用。這是因為 zswap 會在 zram 之前被用作 swap 緩存,並在換出的內存分頁到達 zram 前對其進行攔截和壓縮。在這種情況下,儘管 zramctl(8) 的輸出可能並非如此,實際上大部分 zram 並未被使用。因此,建議在開始前通過內核參數或者 sysfs 設置永久禁用 zswap。
- 不支持在休眠時將內存換出至 zram,即便 zram 被配置在位於永久性存儲的設備上。logind 會阻止休眠到配置在 zram 上的交換空間的嘗試。
mem_limit
參數指定 ZRAM 可存儲的最大壓縮後數據量。一開始可以先嘗試配置大小為物理內存的一半。
臨時應用
參考如下配置一個採用 zstd 壓縮、容量為系統內存大小一半,優先度較高且非持久的 zram 設備 (重啟後失效):
# modprobe zram # zramctl /dev/zram0 --algorithm zstd --size "$(($(grep -Po 'MemTotal:\s*\K\d+' /proc/meminfo)/2))KiB" # mkswap -U clear /dev/zram0 # swapon --discard --priority 100 /dev/zram0
如需禁用,可以重啟或執行以下命令:
# swapoff /dev/zram0 # modprobe -r zram # echo 1 > /sys/module/zswap/parameters/enabled
關於每一步操作、配置選項及潛在問題的詳細信息可以參考 zram 模組的官方文檔。
若需一個持久化的解決方案,請在下述章節所述的方法中任選其一。
使用 udev 規則
以下的案例描述了如何通過單個 udev 規則自動在啟動時配置 zram 內 swap。該案例無需額外的軟體包。
顯式地在啟動時加載模組:
/etc/modules-load.d/zram.conf
zram
創建如下的 udev 規則(請按需調整 disksize
屬性):
/etc/udev/rules.d/99-zram.rules
ACTION=="add", KERNEL=="zram0", ATTR{comp_algorithm}="zstd", ATTR{disksize}="4G", RUN="/usr/bin/mkswap -U clear /dev/%k", TAG+="systemd"
將 /dev/zram
以一個高於默認值的優先度添加到您的 fstab:
/etc/fstab
/dev/zram0 none swap defaults,discard,pri=100 0 0
/dev/disk/by-label/*
和 /dev/disk/by-uuid/*
的符號連結。使用 zram-generator
zram-generator包 提供了 systemd-zram-setup@zramN.service
單元,可自動初始化 zram 設備而無需用戶啟動/啟用相關模板或實例。詳見 zram-generator(8)。
如要使用,只需安裝 zram-generator包,並創建包含如下內容的 /etc/systemd/zram-generator.conf
配置文件:
/etc/systemd/zram-generator.conf
[zram0] zram-size = min(ram / 2, 4096) compression-algorithm = zstd
zram-size
是 zram 設備的大小,單位為 MiB
,你可以使用 ram
指代總內存容量。
compression-algorithm
指定了 zram 設備使用的壓縮算法。執行 cat /sys/block/zram0/comp_algorithm
將顯示所有可用的壓縮算法(包括當前選用的算法)。
詳細信息請參考 zram-generator.conf(5)。
然後執行 daemon-reload,並啟動你配置的 systemd-zram-setup@zramN.service
示例(N
需要與實例編號匹配,該示例中為 systemd-zram-setup@zram0.service
) 。
您可使用 zramctl(8) 或 swapon(8),或是通過查閱 systemd-zram-setup@zramN.service
實例的單元狀態,來檢查您所配置的 /dev/zramN
設備的 swap 狀態。
使用 zramswap
zramswapAUR 提供一個自動化腳本,可配置一個優先度較高、默認為 20% 系統內存容量的 swap。如需讓其自動在啟動時執行,請啟用 zramswap.service
。
使用 zramd
zramdAUR 默認使用 zstd 壓縮自動配置 zram,可通過位於 /etc/default/zramd
的文件修改其配置。通過啟用 zramd.service
可讓其在啟動時自動運行。
提示與技巧
查看 zram 狀態
使用 zramctl(8)。示例:
$ zramctl
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT /dev/zram0 zstd 32G 1.9G 318.6M 424.9M 16 [SWAP]
- DISKSIZE = 32G: 該 zram 設備最多會存儲 32 GiB 的未壓縮數據
- DATA = 1.9G: 目前, 該 zram 設備上存儲著 1.9 GiB (未被壓縮的) 數據
- COMPR = 318.6M: 這 1.9 GiB 未被壓縮的數據被壓縮到了 318.6 MiB
- TOTAL = 424.9M: 包含元信息在內,這 1.9 GiB 未壓縮的數據使用了 424.9 MiB 的物理內存
多個 zram 設備
初始情況下,加載 zram
模塊會創建一個 /dev/zram0
設備。
如果您需要更多的 /dev/zram
設備,使用 num_devices
內核模塊參數指定設備的量,或在之後按需添加它們。
優化 zram 上的 swap
介於 zram 與磁碟 swap 的行為不同,可以配置系統的 swap 以充分利用 zram 的優勢:
/etc/sysctl.d/99-vm-zram-parameters.conf
vm.swappiness = 180 vm.watermark_boost_factor = 0 vm.watermark_scale_factor = 125 vm.page-cluster = 0
該配置的解釋:
這些值與Pop!_OS 中使用的值相同。這條 GitHub 上 Pop!_OS 的 pull request 同時連結到了r/Fedora 上一些用戶所進行的測試,結果顯示 vm.page-cluster = 0
是較為合適的值。此外,他們也發現建議使用較高的 swappniess,這與內核文檔中的建議相符。
默認情況下該值為 60。
- 對於像 zram 或 zswap 這樣在內存中的 swap,以及一些混合式的、在相較文件系統來說更為快速的設備上 swap 的配置,應當考慮 100 以上的值。例如,若 swap 設備上的隨機讀寫平均快於文件系統上隨機讀寫的 2 倍,則 swappiness 值應為 133 (x + 2x = 200, 2x = 133.33)。
在配備硬碟驅動器的系統上,在 zswap 設備上的隨機讀寫會比在文件系統上的讀寫快若干數量級,因此 swappiness 應為 200 左右。甚至是在配備高速固態硬碟的系統上,較高的 swappiness 值也是理想的。
為 zram 塊設備啟用後備設備
在內存壓力較大時,可以配置 zram 將未壓縮內存頁放入指定的塊設備中。
如要手動添加後備設備:
# echo /dev/sdX > /sys/block/zram0/backing_dev
如要通過 zram-generator 為 zram 塊設備添加後備設備,可在 /etc/systemd/zram-generator.conf
中對應的 [zramX]
設備下添加如下內容:
/etc/systemd/zram-generator.conf
writeback-device=/dev/disk/by-partuuid/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
將 zram 用於非 swap 用途
zram 也可以被用作普通的內存塊設備,像是占用較少物理內存,但性能略微下降的 /dev/ram
設備。然而,有幾個問題需要注意:
- 無分區表支持(不會自動創建
/dev/zramxpy
)。 - 塊大小固定為 4 kiB。
顯然,可以通過在 zram 上疊加迴環設備來繞過這一問題。使用 losetup,可以使用 -b
參數指定塊大小,使用 -P
參數處理分區表並自動創建分區迴環設備。
# zramctl -f -s NG
/dev/zramx
將磁碟鏡像複製到新創建的 /dev/zram
:
# losetup -f -b 512 -P /dev/zramx
# ls /dev/loop*
/dev/loop0 /dev/loop0p1 /dev/loop0p2
# mount /dev/loop0p1 /mnt/boot # mount /dev/loop0p2 /mnt/root
- zram 設備編號取決於已有的 zram 設備,其大小應足以存放磁碟鏡像。
-
ls /dev/loop*
的輸出結果取決於磁碟鏡像中的內容。