zram
zram,舊稱為 compcache,是一個用於在內存中創建壓縮的塊設備的 Linux 內核模塊,即帶實時磁盤壓縮的內存盤。通過 zram 創建的塊設備可以用作 swap 或是內存盤。zram 有兩個常見的應用場景,一個是儲存臨時文件(/tmp
),另一個是用作 swap。早期 zram 只有前一個功能,也是它原名 「compcache」 (compressed cache) 的由來。
作為 swap 的使用[編輯 | 編輯原始碼]
在最開始,創建出的 zram 塊設備並不會預留或使用任何內存。僅當有文件需要被或者想要被交換出內存時,它們才會被壓縮並移入 zram 塊設備。因此,zram 塊設備將會根據需要動態地增長或收縮。
例如,考慮一個具備 32 GiB 內存的系統,其上配置了容量為 64 GiB 的 zram。假設 zstd 能夠實現 1:4 的壓縮比率,當被全部占用時,該 zram 塊被壓縮後在物理內存中占用的大小將在 16 GiB 左右。因此:
- 當內存和 zram 均完全被占用時:16 GiB 內存 + 64 GiB zram (在內存中約占用 16 GiB)
- 正常使用且未發生交換時:32 GiB 內存 + 0 GiB zram
- 正常使用且發生少數交換時:30 GiB 內存 + 8 GiB zram (在內存中約占用 2 GiB)
- 不進行任何 zram 配置:32 GiB 內存
可見,zram 總是提供能在內存中存儲更多內容的優勢。
- 假如相關的 zswap 內核功能為啟用狀態,它將阻礙 zram 的有效使用。這是因為 zswap 會在 zram 之前被用作 swap 緩存,並在換出的內存分頁到達 zram 前對其進行攔截和壓縮。在這種情況下,大多數的 zram 其實並未被使用,儘管 zramctl(8) 的輸出可能並非如此。
- 如上所述,在配置 zram 時,zram 設備的大小控制着其能存儲的最大未壓縮數據量,而非最大壓縮後數據量。您可將 zram 的大小配置為與您系統的物理內存容量相等,甚至更大,只需保證數據壓縮後所占用的大小不超過系統物理內存的容量即可。
- 不支持在休眠時將內存換出至 zram,即便 zram 被配置在位於永久性存儲的設備上。logind 會阻止休眠到配置在 zram 上的交換空間的嘗試。
手動應用[編輯 | 編輯原始碼]
首先,通過 sysfs 禁用 zswap。
# echo 0 > /sys/module/zswap/parameters/enabled
接着,配置一個採用 zstd 壓縮、32GiB 容量且優先度較高的 zram 設備 (僅對當前會話生效):
# modprobe zram # zramctl /dev/zram0 --algorithm zstd --size 32G # mkswap -U clear /dev/zram0 # swapon --priority 100 /dev/zram0
如需禁用,可以重啟或執行以下命令:
# swapoff /dev/zram0 # modprobe -r zram # echo 1 > /sys/module/zswap/parameters/enabled
關於每一步操作、配置選項及潛在問題的詳細信息可以參考 zram 模組的官方文檔。
若需一個持久化的解決方案,請在下屬章節所述的方法中任選其一。
使用 udev 規則[編輯 | 編輯原始碼]
以下的案例描述了如何通過單個 udev 規則自動在啟動時配置 zram 內 swap。該案例無需額外的軟件包。
在開始之前,通過內核參數或 sysctl knob 永久性 禁用 zswap。
顯式地 在啟動時加載模組:
/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,pri=100 0 0
/dev/disk/by-label/*
和 /dev/disk/by-uuid/*
的符號鏈接。使用 zram-generator[編輯 | 編輯原始碼]
zram-generator 提供一個 systemd-zram-setup@.service
單元,可自動初始化 zram 設備而無需用戶啟動/啟用相關模板或實例。詳見 zram-generator(8) 和 zram-generator.conf(5)。
在開始之前,通過內核參數或 sysctl knob 永久性 禁用 zswap。[1]
接下來,要創建一個使用 zstd
壓縮、大小為所有可用內存容量一半的 zram swap 設備,只需安裝 zram-generator包,然後創建包含如下內容的 /etc/systemd/zram-generator.conf
配置文件:
/etc/systemd/zram-generator.conf
[zram0] zram-size = ram / 2 compression-algorithm = zstd swap-priority = 100 fs-type = swap
執行 daemon-reload,然後啟動您所配置的 systemd-zram-setup@zramN.service
等實例。
您可使用 zramctl(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 的 PR 同時鏈接到了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 用於非 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*
的輸出結果取決於磁盤鏡像中的內容。