多代 LRU

多代 LRU 是一種替代的 LRU 實現,它優化了頁回收並在記憶體壓力下提高了效能。頁回收決定了核心的快取策略以及過度使用記憶體的能力。它直接影響 kswapd 的 CPU 使用率和 RAM 效率。

快速開始

使用以下配置構建核心。

  • CONFIG_LRU_GEN=y

  • CONFIG_LRU_GEN_ENABLED=y

準備就緒!

執行時選項

/sys/kernel/mm/lru_gen/ 包含以下小節中描述的穩定 ABI。

停用開關

enabled 接受不同的值來啟用或停用以下元件。其預設值取決於 CONFIG_LRU_GEN_ENABLED。除非其中一些有不可預見的副作用,否則所有元件都應該被啟用。當硬體不支援某個元件時,寫入到 enabled 不起作用;即使主開關關閉,有效值也會被接受。

元件

0x0001

多代 LRU 的主開關。

0x0002

當 MMU 設定訪問位時(例如,在 x86 上),以大批次方式清除葉頁表項中的訪問位。這種行為理論上會加劇鎖競爭(mmap_lock)。如果停用它,對於連續對映熱頁的工作負載,多代 LRU 的效能將略微下降,因為它們的訪問位原本可以透過更少、更大的批次清除。

0x0004

當 MMU 設定訪問位時(例如,在 x86 上),同樣清除非葉頁表項中的訪問位。這種行為尚未在 Intel 和 AMD 之外的 x86 變體上驗證。如果停用它,多代 LRU 的效能下降將可以忽略不計。

[yYnN]

應用於上述所有元件。

例如,

echo y >/sys/kernel/mm/lru_gen/enabled
cat /sys/kernel/mm/lru_gen/enabled
0x0007
echo 5 >/sys/kernel/mm/lru_gen/enabled
cat /sys/kernel/mm/lru_gen/enabled
0x0005

記憶體抖動預防

個人電腦對記憶體抖動更敏感,因為它會導致卡頓(渲染 UI 時的延遲)並對使用者體驗產生負面影響。多代 LRU 為大多數沒有 oomd 的筆記本和桌面使用者提供了記憶體抖動預防功能。

使用者可以向 min_ttl_ms 寫入 N 來防止 N 毫秒的工作集被驅逐。如果這個工作集無法保留在記憶體中,OOM killer 將被觸發。換句話說,此選項可作為可調節的洩壓閥,開啟後,它會終止那些可能未被使用的應用程式。

根據人類平均可察覺的延遲(約 100 毫秒),N=1000 通常可以消除因記憶體抖動引起的無法忍受的卡頓。較大的值,例如 N=3000,會使卡頓不那麼明顯,但存在過早觸發 OOM 殺死的風險。

預設值 0 表示停用。

實驗性功能

/sys/kernel/debug/lru_gen 接受以下小節中描述的命令。支援多條命令列,也支援使用分隔符 ,; 進行連線。

/sys/kernel/debug/lru_gen_full 提供額外的統計資訊用於除錯。CONFIG_LRU_GEN_STATS=y 將被驅逐世代的歷史統計資訊保留在此檔案中。

工作集估算

工作集估算衡量一個應用程式在給定時間間隔內需要多少記憶體,並且通常對應用程式的效能影響很小。例如,資料中心希望最佳化作業排程(裝箱)以提高記憶體利用率。當一個新作業到來時,作業排程程式需要確定其管理的每臺伺服器是否可以為這個新作業分配一定量的記憶體,然後才能選擇一個候選。為此,作業排程程式需要估算現有作業的工作集。

讀取時,lru_gen 返回一個在不同時間間隔內訪問的頁數的直方圖,針對每個 memcg 和節點。MAX_NR_GENS 決定了每個直方圖的 bin 數量。這些直方圖是非累積的。

memcg  memcg_id  memcg_path
   node  node_id
       min_gen_nr  age_in_ms  nr_anon_pages  nr_file_pages
       ...
       max_gen_nr  age_in_ms  nr_anon_pages  nr_file_pages

每個 bin 包含一個估計的頁數,這些頁在 age_in_ms 內被訪問過。例如,min_gen_nr 包含最冷的頁,而 max_gen_nr 包含最熱的頁,因為前者的 age_in_ms 最大,後者的最小。

使用者可以向 lru_gen 寫入以下命令,以建立新的世代 max_gen_nr+1

+ memcg_id node_id max_gen_nr [can_swap [force_scan]]

can_swap 預設為 swap 設定,如果將其設定為 1,則在 swap 關閉時強制掃描匿名頁,反之亦然。force_scan 預設為 1,如果將其設定為 0,則它會採用啟發式方法來減少開銷,這可能也會降低覆蓋率。

一個典型的用例是,作業排程程式在某個時間間隔執行此命令以建立新的世代,並根據此時間間隔定義的冷頁大小對其管理的伺服器進行排名。

主動回收

主動回收會在沒有記憶體壓力時觸發頁回收。它通常只針對冷頁。例如,當一個新作業到來時,作業排程程式希望在其選擇的伺服器上主動回收冷頁,以提高成功部署此新作業的機會。

使用者可以向 lru_gen 寫入以下命令,以驅逐小於或等於 min_gen_nr 的世代。

- memcg_id node_id min_gen_nr [swappiness [nr_to_reclaim]]

min_gen_nr 應該小於 max_gen_nr-1,因為 max_gen_nrmax_gen_nr-1 尚未完全老化(相當於活動列表),因此不能被驅逐。swappiness 覆蓋了 /proc/sys/vm/swappiness 中的預設值,有效範圍是 [0-200, max],其中 max 專門用於回收匿名記憶體。nr_to_reclaim 限制了要驅逐的頁數。

一個典型的用例是,作業排程程式在嘗試將新作業部署到伺服器之前執行此命令。如果由於過度估算而未能具體化足夠的冷頁,它會根據從工作集估算步驟中獲得的排名結果在下一臺伺服器上重試。這種力度較小的方法限制了對現有作業的影響。