Linux
當頁面未交換時,是否在 zram 空閒支持頁面上進行交換?
想像一下將 2GiB 換出到 zram 並壓縮到 1GiB 的場景。
一旦記憶體壓力減輕並且 2GiB 逐漸變得未交換,Linux 是否會釋放 1GiB 用於儲存壓縮 zram 頁面的頁面?
如果是這樣,它是否會對現有頁面進行碎片整理?
壓縮頁面中必須有多個頁面,當所有頁面都未交換時會發生什麼?是否所有頁面都保留在記憶體中,直到最後一頁也被釋放?
簡短回答:是的,zram 支持頁面會自動釋放。
通過實驗(核心 5.10.105)檢查後,似乎未使用的 zram 儲存被自動釋放,即使 zram 設備安裝時沒有
discard
.**摘要:**下面的腳本執行一個分配大量記憶體的程序。
zram 使用量(通過 檢查
zramctl
)最初會增加,然後在停止程序並驅逐交換頁面後回到基線。# * I've run this on a freshly booted VM * # zram is mounted with nodiscard to exclude any effects of # `discard`. sudo grep zram /etc/fstab # /dev/zram0 none swap nodiscard,pri=5 # We have ~6 GiB of RAM grep -i memtotal /proc/meminfo # MemTotal: 6386852 kB # Show zram usage. # `DATA` is the total amount of uncompressed data currently stored in zram. zramctl # NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT # /dev/zram0 zstd 3.1G 4K 58B 4K 4 [SWAP] # Start a process that allocates 10 GiB of RAM stress-ng -- --vm-bytes $((10*1024**3)) --vm-keep --vm 1 & # *Wait some time for the stress test command to be swapped out* # zram usage has gone up from 4 KiB to 3.1 GiB zramctl # NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT # /dev/zram0 zstd 3.1G 3.1G 1.1G 1.2G 4 [SWAP] # Stop stress test kill %1 # zram usage decreased from 3.1 GiB to 0.3 GiB zramctl # NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT # /dev/zram0 zstd 3.1G 336.8M 48.6M 57.6M 4 [SWAP] # Read the first byte of all memory pages of all processes. # This evicts all non-kernel swapped pages without using `swapoff`, which might # reset the zram device. sudo ./read_all_mem_pages.rb # Now zram usage is almost back to zero zramctl # NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT # /dev/zram0 zstd 3.1G 18.4M 3.5M 5.9M 4 [SWAP]
來源
read_all_mem_pages.rb
:#!/usr/bin/env ruby def access_all_pages(pid) name = File.basename(File.readlink("/proc/#{pid}/exe")) rescue return puts "#{pid} (#{name})" File.open("/proc/#{pid}/mem", 'r') do |mem| for_each_mem_page(pid) do |page_address| mem.seek(page_address) mem.read(1) rescue nil end end end def for_each_mem_page(pid) File.foreach("/proc/#{pid}/maps") do |line| fields = line.split range, dest = fields[0], fields[-1] next if dest == "[vsyscall]" start, end_ = range.split('-').map { |x| x.to_i(16) } address = start while address < end_ yield address address += 4096 end end end pids = Dir.children('/proc').grep(/^\d+$/).map(&:to_i) pids.each { |pid| access_all_pages(pid) }
預設情況下我會說不,但可以這樣做。
$ lsblk --discard /dev/zram0 NAME DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO zram0 0 4K 2T 0
這意味著
zram0
是一個具有丟棄能力的設備。來自
man swapon
:
-d
,--discard[=policy]
如果交換支持設備支持丟棄或修剪操作,則啟用交換丟棄。
$$ … $$
/etc/fstab
掛載選項 ,discard
或discard=once
也discard=pages
可用於啟用丟棄標誌。人們只需要弄清楚執行
swapon
命令或等效命令的特定 Linux 發行版,並在此位置(或至少是變體)相應地添加swapon--discard
選項或mount選項。discard``=pages