Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,30 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/damon/index.rst
:翻譯:
司延騰 Yanteng Si <siyanteng@loongson.cn>
:校譯:
============
監測數據訪問
============
:doc:`DAMON </mm/damon/index>` 允許輕量級的數據訪問監測。使用DAMON,
用戶可以分析他們系統的內存訪問模式,並優化它們。
.. toctree::
:maxdepth: 2
start
usage
reclaim
lru_sort
@@ -0,0 +1,264 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/damon/lru_sort.rst
:翻譯:
臧雷剛 Leigang Zang <zangleigang@hisilicon.com>
:校譯:
==================
基於DAMON的LRU排序
==================
基於DAMON的LRU排序是一個靜態的內核模塊,旨在用於以主動的、輕量級的數據訪問模型
爲基礎的頁面優先級處理的LRU鏈表上,以使得LRU上的數據訪問模型更爲可信。
哪裏需要主動的LRU排序
=====================
在一個大型系統中,以頁爲粒度的訪問檢測會有比較顯著的開銷,LRU通常不會主動去排序,
而是對部分特殊事件進行部分的、響應式的排序,例如:特殊的用戶請求,系統調用或者
內存壓力。這導致,在有些場景下,LRU不能夠完美的作爲一個可信的數據訪問模型,比如
在內存壓力下對目標內存進行回收。
因爲DAMON能夠儘可能準確的識別數據訪問模型,同時只引起用戶指定範圍的開銷,主動的
執行DAMON_LRU_SORT讓LRU變得更爲可信是有益的,而且這隻需要較少和可控的開銷。
這是如何工作的
==============
DAMON_LRU_SORT使用DAMON尋找熱頁(範圍內的頁面訪問頻率高於用戶指定的閾值)和冷頁
(範圍內的頁面在超過用戶指定的時間無訪問),並提高熱頁和降低冷頁在LRU中的優先級。
爲了避免在排序過程佔用更多的CPU計算資源,可以設置一個CPU佔用時間的約束值。在約
束下,分別提升或者降低更多的熱頁和冷頁。系統管理員也可以配置三個內存水位以控制
在何種條件下自動激活或者停止這種機制。
冷熱閾值和CPU約束的默認值是比較保守的。這意味着,在默認參數下,模塊可以廣泛且無
負作用的使用在常見環境中,同時在只消耗一小部分CPU時間的情況下,給有內存壓力的系
統提供一定水平的冷熱識別。
接口:模塊參數
==============
使用此特性,你首先需要確認你的系統中運行的內核在編譯時啓用了
``CONFIG_DAMON_LRU_SORT=y``.
爲了讓系統管理員打開或者關閉並且調節指定的系統,DAMON_LRU_SORT設計了模塊參數。
這意味着,你可以添加 ``damon_lru_sort.<parameter>=<value>`` 到內核的啓動命令行
參數,或者在 ``/sys/modules/damon_lru_sort/parameters/<parameter>`` 寫入正確的
值。
下邊是每個參數的描述
enabled
-------
打開或者關閉DAMON_LRU_SORT.
你可以通過設置這個參數爲 ``Y`` 來打開DAMON_LRU_SORT。設置爲 ``N`` 關閉
DAMON_LRU_SORT。注意,在基於水位的激活的情況下,DAMON_LRU_SORT有可能不會真正去
監測或者做LRU排序。對這種情況,參考下方關於水位的描述。
commit_inputs
-------------
讓DAMON_LRU_SORT再次讀取輸入參數,除了 ``enabled`` 。
在DAMON_LRU_SORT運行時,新的輸入參數默認不會被應用。一旦這個參數被設置爲 ``Y``
,DAMON_LRU_SORT會再次讀取除了 ``enabled`` 之外的參數。讀取完成後,這個參數會被
設置爲 ``N`` 。如果在讀取時發現有無效參數,DAMON_LRU_SORT會被關閉。
hot_thres_access_freq
---------------------
熱點內存區域的訪問頻率閾值,千分比。
如果一個內存區域的訪問頻率大於等於這個值,DAMON_LRU_SORT把這個區域看作熱區,並
在LRU上把這個區域標記爲已訪問,因些在內存壓力下這部分內存不會被回收。默認爲50%。
cold_min_age
------------
用於識別冷內存區域的時間閾值,單位是微秒。
如果一個內存區域在這個時間內未被訪問過,DAMON_LRU_SORT把這個區域看作冷區,並在
LRU上把這個區域標記爲未訪問,因此在內存壓力下這些內存會首先被回收。默認值爲120
秒。
quota_ms
--------
嘗試LRU鏈表排序的時間限制,單位是毫秒。
DAMON_LRU_SORT在一個時間窗口內(quota_reset_interval_ms)內最多嘗試這麼長時間來
對LRU進行排序。這個可以用來作爲CPU計算資源的約束。如果值爲0,則表示無限制。
默認10毫秒。
quota_reset_interval_ms
-----------------------
配額計時重置週期,毫秒。
配額計時重置週期。即,在quota_reset_interval_ms毫秒內,DAMON_LRU_SORT對LRU進行
排序不會超過quota_ms或者quota_sz。
默認1秒。
wmarks_interval
---------------
水位的檢查週期,單位是微秒。
當DAMON_LRU_SORT使能但是由於水位而不活躍時檢查水位前最小的等待時間。默認值5秒。
wmarks_high
-----------
空閒內存高水位,千分比。
如果空閒內存水位高於這個值,DAMON_LRU_SORT停止工作,不做任何事,除了週期性的檢
查水位。默認200(20%)。
wmarks_mid
----------
空閒內存中間水位,千分比。
如果空閒內存水位在這個值與低水位之間,DAMON_LRU_SORT開始工作,開始檢測並對LRU鏈
表進行排序。默認150(15%)。
wmarks_low
----------
空閒內存低水位,千分比。
如果空閒內存小於這個值,DAMON_LRU_SORT不再工作,不做任何事,除了週期性的檢查水
線。默認50(5%)。
sample_interval
---------------
監測的採樣週期,微秒。
DAMON對冷內存監測的採樣週期。更多細節請參考DAMON文檔 (:doc:`usage`) 。默認5
毫秒。
aggr_interval
-------------
監測的收集週期,微秒。
DAMON對冷內存進行收集的時間週期。更多細節請參考DAMON文檔 (:doc:`usage`) 。默認
100毫秒。
min_nr_regions
--------------
最小監測區域數量。
對冷內存區域監測的最小數量。這個值可以作爲監測質量的下限。不過,這個值設置的過
大會增加開銷。更多細節請參考DAMON文檔 (:doc:`usage`) 。默認值爲10。
max_nr_regions
--------------
最大監測區域數量。
對冷內存區域監測的最大數量。這個值可以作爲監測質量的上限。然而,這個值設置的過
低會導致監測結果變差。更多細節請參考DAMON文檔 (:doc:`usage`) 。默認值爲1000。
monitor_region_start
--------------------
目標內存區域的起始物理地址。
DAMON_LRU_SORT要處理的目標內存區域的起始物理地址。默認,使用系統最大內存。
monitor_region_end
------------------
目標內存區域的結束物理地址。
DAMON_LRU_SORT要處理的目標內存區域的結束物理地址。默認,使用系統最大內存。
kdamond_pid
-----------
DAMON線程的PID。
如果DAMON_LRU_SORT是使能的,這個表示任務線程的PID。其它情況爲-1。
nr_lru_sort_tried_hot_regions
-----------------------------
被嘗試進行LRU排序的熱內存區域的數量。
bytes_lru_sort_tried_hot_regions
--------------------------------
被嘗試進行LRU排序的熱內存區域的大小(字節)。
nr_lru_sorted_hot_regions
-------------------------
成功進行LRU排序的熱內存區域的數量。
bytes_lru_sorted_hot_regions
----------------------------
成功進行LRU排序的熱內存區域的大小(字節)。
nr_hot_quota_exceeds
--------------------
熱區域時間約束超過限制的次數。
nr_lru_sort_tried_cold_regions
------------------------------
被嘗試進行LRU排序的冷內存區域的數量。
bytes_lru_sort_tried_cold_regions
---------------------------------
被嘗試進行LRU排序的冷內存區域的大小(字節)。
nr_lru_sorted_cold_regions
--------------------------
成功進行LRU排序的冷內存區域的數量。
bytes_lru_sorted_cold_regions
-----------------------------
成功進行LRU排序的冷內存區域的大小(字節)。
nr_cold_quota_exceeds
---------------------
冷區域時間約束超過限制的次數。
Example
=======
如下是一個運行時的命令示例,使DAMON_LRU_SORT查找訪問頻率超過50%的區域並對其進行
LRU的優先級的提升,同時降低那些超過120秒無人訪問的內存區域的優先級。優先級的處
理被限制在最多1%的CPU以避免DAMON_LRU_SORT消費過多CPU時間。在系統空閒內存超過50%
時DAMON_LRU_SORT停止工作,並在低於40%時重新開始工作。如果DAMON_RECLAIM沒有取得
進展且空閒內存低於20%,再次讓DAMON_LRU_SORT停止工作,以此回退到以LRU鏈表爲基礎
以頁面爲單位的內存回收上。 ::
# cd /sys/modules/damon_lru_sort/parameters
# echo 500 > hot_thres_access_freq
# echo 120000000 > cold_min_age
# echo 10 > quota_ms
# echo 1000 > quota_reset_interval_ms
# echo 500 > wmarks_high
# echo 400 > wmarks_mid
# echo 200 > wmarks_low
# echo Y > enabled
@@ -0,0 +1,229 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/damon/reclaim.rst
:翻譯:
司延騰 Yanteng Si <siyanteng@loongson.cn>
:校譯:
===============
基於DAMON的回收
===============
基於DAMON的回收(DAMON_RECLAIM)是一個靜態的內核模塊,旨在用於輕度內存壓力下的主動和輕
量級的回收。它的目的不是取代基於LRU列表的頁面回收,而是有選擇地用於不同程度的內存壓力和要
求。
哪些地方需要主動回收?
======================
在一般的內存超量使用(over-committed systems,虛擬化相關術語)的系統上,主動回收冷頁
有助於節省內存和減少延遲高峯,這些延遲是由直接回收進程或kswapd的CPU消耗引起的,同時只產
生最小的性能下降 [1]_ [2]_ 。
基於空閒頁報告 [3]_ 的內存過度承諾的虛擬化系統就是很好的例子。在這樣的系統中,客戶機
向主機報告他們的空閒內存,而主機則將報告的內存重新分配給其他客戶。因此,系統的內存得到了充
分的利用。然而,客戶可能不那麼節省內存,主要是因爲一些內核子系統和用戶空間應用程序被設計爲
使用盡可能多的內存。然後,客戶機可能只向主機報告少量的內存是空閒的,導致系統的內存利用率下降。
在客戶中運行主動回收可以緩解這個問題。
它是如何工作的?
================
DAMON_RECLAIM找到在特定時間內沒有被訪問的內存區域並分頁。爲了避免它在分頁操作中消耗過多
的CPU,可以配置一個速度限制。在這個速度限制下,它首先分頁出那些沒有被訪問過的內存區域。系
統管理員還可以配置在什麼情況下這個方案應該自動激活和停用三個內存壓力水位。
接口: 模塊參數
==============
要使用這個功能,你首先要確保你的系統運行在一個以 ``CONFIG_DAMON_RECLAIM=y`` 構建的內
核上。
爲了讓系統管理員啓用或禁用它,併爲給定的系統進行調整,DAMON_RECLAIM利用了模塊參數。也就
是說,你可以把 ``damon_reclaim.<parameter>=<value>`` 放在內核啓動命令行上,或者把
適當的值寫入 ``/sys/module/damon_reclaim/parameters/<parameter>`` 文件。
下面是每個參數的描述。
enabled
-------
啓用或禁用DAMON_RECLAIM。
你可以通過把這個參數的值設置爲 ``Y`` 來啓用DAMON_RCLAIM,把它設置爲 ``N`` 可以禁用
DAMON_RECLAIM。注意,由於基於水位的激活條件,DAMON_RECLAIM不能進行真正的監測和回收。
這一點請參考下面關於水位參數的描述。
min_age
-------
識別冷內存區域的時間閾值,單位是微秒。
如果一個內存區域在這個時間或更長的時間內沒有被訪問,DAMON_RECLAIM會將該區域識別爲冷的,
並回收它。
默認爲120秒。
quota_ms
--------
回收的時間限制,以毫秒爲單位。
DAMON_RECLAIM 試圖在一個時間窗口(quota_reset_interval_ms)內只使用到這個時間,以
嘗試回收冷頁。這可以用來限制DAMON_RECLAIM的CPU消耗。如果該值爲零,則該限制被禁用。
默認爲10ms。
quota_sz
--------
回收的內存大小限制,單位爲字節。
DAMON_RECLAIM 收取在一個時間窗口(quota_reset_interval_ms)內試圖回收的內存量,並
使其不超過這個限制。這可以用來限制CPU和IO的消耗。如果該值爲零,則限制被禁用。
默認情況下是128 MiB。
quota_reset_interval_ms
-----------------------
時間/大小配額收取重置間隔,單位爲毫秒。
時間(quota_ms)和大小(quota_sz)的配額的目標重置間隔。也就是說,DAMON_RECLAIM在
嘗試回收‘不’超過quota_ms毫秒或quota_sz字節的內存。
默認爲1秒。
wmarks_interval
---------------
當DAMON_RECLAIM被啓用但由於其水位規則而不活躍時,在檢查水位之前的最小等待時間。
wmarks_high
-----------
高水位的可用內存率(每千字節)。
如果系統的可用內存(以每千字節爲單位)高於這個數值,DAMON_RECLAIM就會變得不活躍,所以
它什麼也不做,只是定期檢查水位。
wmarks_mid
----------
中間水位的可用內存率(每千字節)。
如果系統的空閒內存(以每千字節爲單位)在這個和低水位線之間,DAMON_RECLAIM就會被激活,
因此開始監測和回收。
wmarks_low
----------
低水位的可用內存率(每千字節)。
如果系統的空閒內存(以每千字節爲單位)低於這個數值,DAMON_RECLAIM就會變得不活躍,所以
它除了定期檢查水位外什麼都不做。在這種情況下,系統會退回到基於LRU列表的頁面粒度回收邏輯。
sample_interval
---------------
監測的採樣間隔,單位是微秒。
DAMON用於監測冷內存的採樣間隔。更多細節請參考DAMON文檔 (:doc:`usage`) 。
aggr_interval
-------------
監測的聚集間隔,單位是微秒。
DAMON對冷內存監測的聚集間隔。更多細節請參考DAMON文檔 (:doc:`usage`)。
min_nr_regions
--------------
監測區域的最小數量。
DAMON用於冷內存監測的最小監測區域數。這可以用來設置監測質量的下限。但是,設
置的太高可能會導致監測開銷的增加。更多細節請參考DAMON文檔 (:doc:`usage`) 。
max_nr_regions
--------------
監測區域的最大數量。
DAMON用於冷內存監測的最大監測區域數。這可以用來設置監測開銷的上限值。但是,
設置得太低可能會導致監測質量不好。更多細節請參考DAMON文檔 (:doc:`usage`) 。
monitor_region_start
--------------------
目標內存區域的物理地址起點。
DAMON_RECLAIM將對其進行工作的內存區域的起始物理地址。也就是說,DAMON_RECLAIM
將在這個區域中找到冷的內存區域並進行回收。默認情況下,該區域使用最大系統內存區。
monitor_region_end
------------------
目標內存區域的結束物理地址。
DAMON_RECLAIM將對其進行工作的內存區域的末端物理地址。也就是說,DAMON_RECLAIM將
在這個區域內找到冷的內存區域並進行回收。默認情況下,該區域使用最大系統內存區。
kdamond_pid
-----------
DAMON線程的PID。
如果DAMON_RECLAIM被啓用,這將成爲工作線程的PID。否則,爲-1。
nr_reclaim_tried_regions
------------------------
試圖通過DAMON_RECLAIM回收的內存區域的數量。
bytes_reclaim_tried_regions
---------------------------
試圖通過DAMON_RECLAIM回收的內存區域的總字節數。
nr_reclaimed_regions
--------------------
通過DAMON_RECLAIM成功回收的內存區域的數量。
bytes_reclaimed_regions
-----------------------
通過DAMON_RECLAIM成功回收的內存區域的總字節數。
nr_quota_exceeds
----------------
超過時間/空間配額限制的次數。
例子
====
下面的運行示例命令使DAMON_RECLAIM找到30秒或更長時間沒有訪問的內存區域並“回收”?
爲了避免DAMON_RECLAIM在分頁操作中消耗過多的CPU時間,回收被限制在每秒1GiB以內。
它還要求DAMON_RECLAIM在系統的可用內存率超過50%時不做任何事情,但如果它低於40%時
就開始真正的工作。如果DAMON_RECLAIM沒有取得進展,因此空閒內存率低於20%,它會要求
DAMON_RECLAIM再次什麼都不做,這樣我們就可以退回到基於LRU列表的頁面粒度回收了::
# cd /sys/module/damon_reclaim/parameters
# echo 30000000 > min_age
# echo $((1 * 1024 * 1024 * 1024)) > quota_sz
# echo 1000 > quota_reset_interval_ms
# echo 500 > wmarks_high
# echo 400 > wmarks_mid
# echo 200 > wmarks_low
# echo Y > enabled
.. [1] https://research.google/pubs/pub48551/
.. [2] https://lwn.net/Articles/787611/
.. [3] https://www.kernel.org/doc/html/latest/mm/free_page_reporting.html
@@ -0,0 +1,125 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/damon/start.rst
:翻譯:
司延騰 Yanteng Si <siyanteng@loongson.cn>
:校譯:
========
入門指南
========
本文通過演示DAMON的默認用戶空間工具,簡要地介紹瞭如何使用DAMON。請注意,爲了簡潔
起見,本文檔只描述了它的部分功能。更多細節請參考該工具的使用文檔。
`doc <https://github.com/damonitor/damo/blob/next/USAGE.md>`_ .
前提條件
========
內核
----
首先,你要確保你當前系統中跑的內核構建時選定了這個功能選項 ``CONFIG_DAMON_*=y``.
用戶空間工具
------------
在演示中,我們將使用DAMON的默認用戶空間工具,稱爲DAMON Operator(DAMO)。它可以在
https://github.com/damonitor/damo找到。下面的例子假設DAMO在你的$PATH上。當然,但
這並不是強制性的。
因爲DAMO使用了DAMON的sysfs接口(詳情請參考:doc:`usage`),你應該確保
:doc:`sysfs </filesystems/sysfs>` 被掛載。
記錄數據訪問模式
================
下面的命令記錄了一個程序的內存訪問模式,並將監測結果保存到文件中。 ::
$ git clone https://github.com/sjp38/masim
$ cd masim; make; ./masim ./configs/zigzag.cfg &
$ sudo damo record -o damon.data $(pidof masim)
命令的前兩行下載了一個人工內存訪問生成器程序並在後臺運行。生成器將重複地逐一訪問兩個
100 MiB大小的內存區域。你可以用你的真實工作負載來代替它。最後一行要求 ``damo`` 將
訪問模式記錄在 ``damon.data`` 文件中。
將記錄的模式可視化
==================
你可以在heatmap中直觀地看到這種模式,顯示哪個內存區域(X軸)何時被訪問(Y軸)以及訪
問的頻率(數字)。::
$ sudo damo report heats --heatmap stdout
22222222222222222222222222222222222222211111111111111111111111111111111111111100
44444444444444444444444444444444444444434444444444444444444444444444444444443200
44444444444444444444444444444444444444433444444444444444444444444444444444444200
33333333333333333333333333333333333333344555555555555555555555555555555555555200
33333333333333333333333333333333333344444444444444444444444444444444444444444200
22222222222222222222222222222222222223355555555555555555555555555555555555555200
00000000000000000000000000000000000000288888888888888888888888888888888888888400
00000000000000000000000000000000000000288888888888888888888888888888888888888400
33333333333333333333333333333333333333355555555555555555555555555555555555555200
88888888888888888888888888888888888888600000000000000000000000000000000000000000
88888888888888888888888888888888888888600000000000000000000000000000000000000000
33333333333333333333333333333333333333444444444444444444444444444444444444443200
00000000000000000000000000000000000000288888888888888888888888888888888888888400
[...]
# access_frequency: 0 1 2 3 4 5 6 7 8 9
# x-axis: space (139728247021568-139728453431248: 196.848 MiB)
# y-axis: time (15256597248362-15326899978162: 1 m 10.303 s)
# resolution: 80x40 (2.461 MiB and 1.758 s for each character)
你也可以直觀地看到工作集的大小分佈,按大小排序。::
$ sudo damo report wss --range 0 101 10
# <percentile> <wss>
# target_id 18446632103789443072
# avr: 107.708 MiB
0 0 B | |
10 95.328 MiB |**************************** |
20 95.332 MiB |**************************** |
30 95.340 MiB |**************************** |
40 95.387 MiB |**************************** |
50 95.387 MiB |**************************** |
60 95.398 MiB |**************************** |
70 95.398 MiB |**************************** |
80 95.504 MiB |**************************** |
90 190.703 MiB |********************************************************* |
100 196.875 MiB |***********************************************************|
在上述命令中使用 ``--sortby`` 選項,可以顯示工作集的大小是如何按時間順序變化的。::
$ sudo damo report wss --range 0 101 10 --sortby time
# <percentile> <wss>
# target_id 18446632103789443072
# avr: 107.708 MiB
0 3.051 MiB | |
10 190.703 MiB |***********************************************************|
20 95.336 MiB |***************************** |
30 95.328 MiB |***************************** |
40 95.387 MiB |***************************** |
50 95.332 MiB |***************************** |
60 95.320 MiB |***************************** |
70 95.398 MiB |***************************** |
80 95.398 MiB |***************************** |
90 95.340 MiB |***************************** |
100 95.398 MiB |***************************** |
數據訪問模式感知的內存管理
==========================
以下三個命令使每一個大小>=4K的內存區域在你的工作負載中沒有被訪問>=60秒,就會被換掉。 ::
$ echo "#min-size max-size min-acc max-acc min-age max-age action" > test_scheme
$ echo "4K max 0 0 60s max pageout" >> test_scheme
$ damo schemes -c test_scheme <pid of your workload>
@@ -0,0 +1,346 @@
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/damon/usage.rst
:翻譯:
司延騰 Yanteng Si <siyanteng@loongson.cn>
:校譯:
========
詳細用法
========
DAMON 爲不同的用戶提供了下面這些接口。
- *DAMON用戶空間工具。*
`這 <https://github.com/damonitor/damo>`_ 爲有這特權的人, 如系統管理員,希望有一個剛好
可以工作的人性化界面。
使用它,用戶可以以人性化的方式使用DAMON的主要功能。不過,它可能不會爲特殊情況進行高度調整。
它同時支持虛擬和物理地址空間的監測。更多細節,請參考它的 `使用文檔
<https://github.com/damonitor/damo/blob/next/USAGE.md>`_。
- *sysfs接口。*
:ref:`這 <sysfs_interface>` 是爲那些希望更高級的使用DAMON的特權用戶空間程序員準備的。
使用它,用戶可以通過讀取和寫入特殊的sysfs文件來使用DAMON的主要功能。因此,你可以編寫和使
用你個性化的DAMON sysfs包裝程序,代替你讀/寫sysfs文件。 `DAMON用戶空間工具
<https://github.com/damonitor/damo>`_ 就是這種程序的一個例子 它同時支持虛擬和物理地址
空間的監測。
- *內核空間編程接口。*
:doc:`這 </mm/damon/api>` 這是爲內核空間程序員準備的。使用它,用戶可以通過爲你編寫內
核空間的DAMON應用程序,最靈活有效地利用DAMON的每一個功能。你甚至可以爲各種地址空間擴展DAMON。
詳細情況請參考接口 :doc:`文件 </mm/damon/api>`。
sysfs接口
=========
DAMON的sysfs接口是在定義 ``CONFIG_DAMON_SYSFS`` 時建立的。它在其sysfs目錄下創建多
個目錄和文件, ``<sysfs>/kernel/mm/damon/`` 。你可以通過對該目錄下的文件進行寫入和
讀取來控制DAMON。
對於一個簡短的例子,用戶可以監測一個給定工作負載的虛擬地址空間,如下所示::
# cd /sys/kernel/mm/damon/admin/
# echo 1 > kdamonds/nr_kdamonds && echo 1 > kdamonds/0/contexts/nr_contexts
# echo vaddr > kdamonds/0/contexts/0/operations
# echo 1 > kdamonds/0/contexts/0/targets/nr_targets
# echo $(pidof <workload>) > kdamonds/0/contexts/0/targets/0/pid_target
# echo on > kdamonds/0/state
文件層次結構
------------
DAMON sysfs接口的文件層次結構如下圖所示。在下圖中,父子關係用縮進表示,每個目錄有
``/`` 後綴,每個目錄中的文件用逗號(",")分開。 ::
/sys/kernel/mm/damon/admin
│ kdamonds/nr_kdamonds
│ │ 0/state,pid
│ │ │ contexts/nr_contexts
│ │ │ │ 0/operations
│ │ │ │ │ monitoring_attrs/
│ │ │ │ │ │ intervals/sample_us,aggr_us,update_us
│ │ │ │ │ │ nr_regions/min,max
│ │ │ │ │ targets/nr_targets
│ │ │ │ │ │ 0/pid_target
│ │ │ │ │ │ │ regions/nr_regions
│ │ │ │ │ │ │ │ 0/start,end
│ │ │ │ │ │ │ │ ...
│ │ │ │ │ │ ...
│ │ │ │ │ schemes/nr_schemes
│ │ │ │ │ │ 0/action
│ │ │ │ │ │ │ access_pattern/
│ │ │ │ │ │ │ │ sz/min,max
│ │ │ │ │ │ │ │ nr_accesses/min,max
│ │ │ │ │ │ │ │ age/min,max
│ │ │ │ │ │ │ quotas/ms,bytes,reset_interval_ms
│ │ │ │ │ │ │ │ weights/sz_permil,nr_accesses_permil,age_permil
│ │ │ │ │ │ │ watermarks/metric,interval_us,high,mid,low
│ │ │ │ │ │ │ stats/nr_tried,sz_tried,nr_applied,sz_applied,qt_exceeds
│ │ │ │ │ │ │ tried_regions/
│ │ │ │ │ │ │ │ 0/start,end,nr_accesses,age
│ │ │ │ │ │ │ │ ...
│ │ │ │ │ │ ...
│ │ │ │ ...
│ │ ...
根
--
DAMON sysfs接口的根是 ``<sysfs>/kernel/mm/damon/`` ,它有一個名爲 ``admin`` 的
目錄。該目錄包含特權用戶空間程序控制DAMON的文件。擁有根權限的用戶空間工具或deamons可以
使用這個目錄。
kdamonds/
---------
與監測相關的信息包括請求規格和結果被稱爲DAMON上下文。DAMON用一個叫做kdamond的內核線程
執行每個上下文,多個kdamonds可以並行運行。
在 ``admin`` 目錄下,有一個目錄,即``kdamonds``,它有控制kdamonds的文件存在。在開始
時,這個目錄只有一個文件,``nr_kdamonds``。向該文件寫入一個數字(``N``),就會創建名爲
``0`` 到 ``N-1`` 的子目錄數量。每個目錄代表每個kdamond。
kdamonds/<N>/
-------------
在每個kdamond目錄中,存在兩個文件(``state`` 和 ``pid`` )和一個目錄( ``contexts`` )。
讀取 ``state`` 時,如果kdamond當前正在運行,則返回 ``on`` ,如果沒有運行則返回 ``off`` 。
寫入 ``on`` 或 ``off`` 使kdamond處於狀態。向 ``state`` 文件寫 ``update_schemes_stats`` ,
更新kdamond的每個基於DAMON的操作方案的統計文件的內容。關於統計信息的細節,請參考
:ref:`stats section <sysfs_schemes_stats>`. 將 ``update_schemes_tried_regions`` 寫到
``state`` 文件,爲kdamond的每個基於DAMON的操作方案,更新基於DAMON的操作方案動作的嘗試區域目錄。
將`clear_schemes_tried_regions`寫入`state`文件,清除kdamond的每個基於DAMON的操作方案的動作
嘗試區域目錄。 關於基於DAMON的操作方案動作嘗試區域目錄的細節,請參考:ref:tried_regions 部分
<sysfs_schemes_tried_regions>`。
如果狀態爲 ``on``,讀取 ``pid`` 顯示kdamond線程的pid。
``contexts`` 目錄包含控制這個kdamond要執行的監測上下文的文件。
kdamonds/<N>/contexts/
----------------------
在開始時,這個目錄只有一個文件,即 ``nr_contexts`` 。向該文件寫入一個數字( ``N`` ),就會創
建名爲``0`` 到 ``N-1`` 的子目錄數量。每個目錄代表每個監測背景。目前,每個kdamond只支持
一個上下文,所以只有 ``0`` 或 ``1`` 可以被寫入文件。
contexts/<N>/
-------------
在每個上下文目錄中,存在一個文件(``operations``)和三個目錄(``monitoring_attrs``,
``targets``, 和 ``schemes``)。
DAMON支持多種類型的監測操作,包括對虛擬地址空間和物理地址空間的監測。你可以通過向文件
中寫入以下關鍵詞之一,並從文件中讀取,來設置和獲取DAMON將爲上下文使用何種類型的監測操作。
- vaddr: 監測特定進程的虛擬地址空間
- paddr: 監視系統的物理地址空間
contexts/<N>/monitoring_attrs/
------------------------------
用於指定監測屬性的文件,包括所需的監測質量和效率,都在 ``monitoring_attrs`` 目錄中。
具體來說,這個目錄下有兩個目錄,即 ``intervals`` 和 ``nr_regions`` 。
在 ``intervals`` 目錄下,存在DAMON的採樣間隔(``sample_us``)、聚集間隔(``aggr_us``)
和更新間隔(``update_us``)三個文件。你可以通過寫入和讀出這些文件來設置和獲取微秒級的值。
在 ``nr_regions`` 目錄下,有兩個文件分別用於DAMON監測區域的下限和上限(``min`` 和 ``max`` ),
這兩個文件控制着監測的開銷。你可以通過向這些文件的寫入和讀出來設置和獲取這些值。
關於間隔和監測區域範圍的更多細節,請參考設計文件 (:doc:`/mm/damon/design`)。
contexts/<N>/targets/
---------------------
在開始時,這個目錄只有一個文件 ``nr_targets`` 。向該文件寫入一個數字(``N``),就可以創建
名爲 ``0`` 到 ``N-1`` 的子目錄的數量。每個目錄代表每個監測目標。
targets/<N>/
------------
在每個目標目錄中,存在一個文件(``pid_target``)和一個目錄(``regions``)。
如果你把 ``vaddr`` 寫到 ``contexts/<N>/operations`` 中,每個目標應該是一個進程。你
可以通過將進程的pid寫到 ``pid_target`` 文件中來指定DAMON的進程。
targets/<N>/regions
-------------------
當使用 ``vaddr`` 監測操作集時( ``vaddr`` 被寫入 ``contexts/<N>/operations`` 文
件),DAMON自動設置和更新監測目標區域,這樣就可以覆蓋目標進程的整個內存映射。然而,用戶可
能希望將初始監測區域設置爲特定的地址範圍。
相反,當使用 ``paddr`` 監測操作集時,DAMON不會自動設置和更新監測目標區域( ``paddr``
被寫入 ``contexts/<N>/operations`` 中)。因此,在這種情況下,用戶應該自己設置監測目標
區域。
在這種情況下,用戶可以按照自己的意願明確設置初始監測目標區域,將適當的值寫入該目錄下的文件。
開始時,這個目錄只有一個文件, ``nr_regions`` 。向該文件寫入一個數字(``N``),就可以創
建名爲 ``0`` 到 ``N-1`` 的子目錄。每個目錄代表每個初始監測目標區域。
regions/<N>/
------------
在每個區域目錄中,你會發現兩個文件( ``start`` 和 ``end`` )。你可以通過向文件寫入
和從文件中讀出,分別設置和獲得初始監測目標區域的起始和結束地址。
每個區域不應該與其他區域重疊。 目錄“N”的“結束”應等於或小於目錄“N+1”的“開始”。
contexts/<N>/schemes/
---------------------
對於一版的基於DAMON的數據訪問感知的內存管理優化,用戶通常希望系統對特定訪問模式的內存區
域應用內存管理操作。DAMON從用戶那裏接收這種形式化的操作方案,並將這些方案應用於目標內存
區域。用戶可以通過讀取和寫入這個目錄下的文件來獲得和設置這些方案。
在開始時,這個目錄只有一個文件,``nr_schemes``。向該文件寫入一個數字(``N``),就可以
創建名爲``0``到``N-1``的子目錄的數量。每個目錄代表每個基於DAMON的操作方案。
schemes/<N>/
------------
在每個方案目錄中,存在五個目錄(``access_pattern``、``quotas``、``watermarks``、
``stats`` 和 ``tried_regions``)和一個文件(``action``)。
``action`` 文件用於設置和獲取你想應用於具有特定訪問模式的內存區域的動作。可以寫入文件
和從文件中讀取的關鍵詞及其含義如下。
- ``willneed``: 對有 ``MADV_WILLNEED`` 的區域調用 ``madvise()`` 。
- ``cold``: 對具有 ``MADV_COLD`` 的區域調用 ``madvise()`` 。
- ``pageout``: 爲具有 ``MADV_PAGEOUT`` 的區域調用 ``madvise()`` 。
- ``hugepage``: 爲帶有 ``MADV_HUGEPAGE`` 的區域調用 ``madvise()`` 。
- ``nohugepage``: 爲帶有 ``MADV_NOHUGEPAGE`` 的區域調用 ``madvise()``。
- ``lru_prio``: 在其LRU列表上對區域進行優先排序。
- ``lru_deprio``: 對區域的LRU列表進行降低優先處理。
- ``stat``: 什麼都不做,只計算統計數據
schemes/<N>/access_pattern/
---------------------------
每個基於DAMON的操作方案的目標訪問模式由三個範圍構成,包括以字節爲單位的區域大小、每個
聚合區間的監測訪問次數和區域年齡的聚合區間數。
在 ``access_pattern`` 目錄下,存在三個目錄( ``sz``, ``nr_accesses``, 和 ``age`` ),
每個目錄有兩個文件(``min`` 和 ``max`` )。你可以通過向 ``sz``, ``nr_accesses``, 和
``age`` 目錄下的 ``min`` 和 ``max`` 文件分別寫入和讀取來設置和獲取給定方案的訪問模式。
schemes/<N>/quotas/
-------------------
每個 ``動作`` 的最佳 ``目標訪問模式`` 取決於工作負載,所以不容易找到。更糟糕的是,將某些動作
的方案設置得過於激進會造成嚴重的開銷。爲了避免這種開銷,用戶可以爲每個方案限制時間和大小配額。
具體來說,用戶可以要求DAMON儘量只使用特定的時間(``時間配額``)來應用動作,並且在給定的時間間
隔(``重置間隔``)內,只對具有目標訪問模式的內存區域應用動作,而不使用特定數量(``大小配額``)。
當預計超過配額限制時,DAMON會根據 ``目標訪問模式`` 的大小、訪問頻率和年齡,對找到的內存區域
進行優先排序。爲了進行個性化的優先排序,用戶可以爲這三個屬性設置權重。
在 ``quotas`` 目錄下,存在三個文件(``ms``, ``bytes``, ``reset_interval_ms``)和一個
目錄(``weights``),其中有三個文件(``sz_permil``, ``nr_accesses_permil``, 和
``age_permil``)。
你可以設置以毫秒爲單位的 ``時間配額`` ,以字節爲單位的 ``大小配額`` ,以及以毫秒爲單位的 ``重
置間隔`` ,分別向這三個文件寫入數值。你還可以通過向 ``weights`` 目錄下的三個文件寫入數值來設
置大小、訪問頻率和年齡的優先權,單位爲千分之一。
schemes/<N>/watermarks/
-----------------------
爲了便於根據系統狀態激活和停用每個方案,DAMON提供了一個稱爲水位的功能。該功能接收五個值,稱爲
``度量`` 、``間隔`` 、``高`` 、``中`` 、``低`` 。``度量值`` 是指可以測量的系統度量值,如
自由內存比率。如果系統的度量值 ``高`` 於memoent的高值或 ``低`` 於低值,則該方案被停用。如果
該值低於 ``中`` ,則該方案被激活。
在水位目錄下,存在五個文件(``metric``, ``interval_us``,``high``, ``mid``, and ``low``)
用於設置每個值。你可以通過向這些文件的寫入來分別設置和獲取這五個值。
可以寫入 ``metric`` 文件的關鍵詞和含義如下。
- none: 忽略水位
- free_mem_rate: 系統的自由內存率(千分比)。
``interval`` 應以微秒爲單位寫入。
schemes/<N>/stats/
------------------
DAMON統計每個方案被嘗試應用的區域的總數量和字節數,每個方案被成功應用的區域的兩個數字,以及
超過配額限制的總數量。這些統計數據可用於在線分析或調整方案。
可以通過讀取 ``stats`` 目錄下的文件(``nr_tried``, ``sz_tried``, ``nr_applied``,
``sz_applied``, 和 ``qt_exceeds``))分別檢索這些統計數據。這些文件不是實時更新的,所以
你應該要求DAMON sysfs接口通過在相關的 ``kdamonds/<N>/state`` 文件中寫入一個特殊的關鍵字
``update_schemes_stats`` 來更新統計信息的文件內容。
schemes/<N>/tried_regions/
--------------------------
當一個特殊的關鍵字 ``update_schemes_tried_regions`` 被寫入相關的 ``kdamonds/<N>/state``
文件時,DAMON會在這個目錄下創建從 ``0`` 開始命名的整數目錄。每個目錄包含的文件暴露了關於每個
內存區域的詳細信息,在下一個 :ref:`聚集區間 <sysfs_monitoring_attrs>`,相應的方案的 ``動作``
已經嘗試在這個目錄下應用。這些信息包括地址範圍、``nr_accesses`` 以及區域的 ``年齡`` 。
當另一個特殊的關鍵字 ``clear_schemes_tried_regions`` 被寫入相關的 ``kdamonds/<N>/state``
文件時,這些目錄將被刪除。
tried_regions/<N>/
------------------
在每個區域目錄中,你會發現四個文件(``start``, ``end``, ``nr_accesses``, and ``age``)。
讀取這些文件將顯示相應的基於DAMON的操作方案 ``動作`` 試圖應用的區域的開始和結束地址、``nr_accesses``
和 ``年齡`` 。
用例
~~~~
下面的命令應用了一個方案:”如果一個大小爲[4KiB, 8KiB]的內存區域在[10, 20]的聚合時間間隔內
顯示出每一個聚合時間間隔[0, 5]的訪問量,請分頁該區域。對於分頁,每秒最多隻能使用10ms,而且每
秒分頁不能超過1GiB。在這一限制下,首先分頁出具有較長年齡的內存區域。另外,每5秒鐘檢查一次系統
的可用內存率,當可用內存率低於50%時開始監測和分頁,但如果可用內存率大於60%,或低於30%,則停
止監測。“ ::
# cd <sysfs>/kernel/mm/damon/admin
# # populate directories
# echo 1 > kdamonds/nr_kdamonds; echo 1 > kdamonds/0/contexts/nr_contexts;
# echo 1 > kdamonds/0/contexts/0/schemes/nr_schemes
# cd kdamonds/0/contexts/0/schemes/0
# # set the basic access pattern and the action
# echo 4096 > access_pattern/sz/min
# echo 8192 > access_pattern/sz/max
# echo 0 > access_pattern/nr_accesses/min
# echo 5 > access_pattern/nr_accesses/max
# echo 10 > access_pattern/age/min
# echo 20 > access_pattern/age/max
# echo pageout > action
# # set quotas
# echo 10 > quotas/ms
# echo $((1024*1024*1024)) > quotas/bytes
# echo 1000 > quotas/reset_interval_ms
# # set watermark
# echo free_mem_rate > watermarks/metric
# echo 5000000 > watermarks/interval_us
# echo 600 > watermarks/high
# echo 500 > watermarks/mid
# echo 300 > watermarks/low
請注意,我們強烈建議使用用戶空間的工具,如 `damo <https://github.com/damonitor/damo>`_ ,
而不是像上面那樣手動讀寫文件。以上只是一個例子。
監測結果的監測點
================
DAMON通過一個tracepoint ``damon:damon_aggregated`` 提供監測結果. 當監測開啓時,你可
以記錄追蹤點事件,並使用追蹤點支持工具如perf顯示結果。比如說::
# echo on > monitor_on_DEPRECATED
# perf record -e damon:damon_aggregated &
# sleep 5
# kill 9 $(pidof perf)
# echo off > monitor_on_DEPRECATED
# perf script
@@ -0,0 +1,50 @@
.. include:: ../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/index.rst
:翻譯:
徐鑫 xu xin <xu.xin16@zte.com.cn>
========
內存管理
========
Linux內存管理子系統,顧名思義,是負責系統中的內存管理。它包括了虛擬內存與請求
分頁的實現,內核內部結構和用戶空間程序的內存分配、將文件映射到進程地址空間以
及許多其他很酷的事情。
Linux內存管理是一個具有許多可配置設置的複雜系統, 且這些設置中的大多數都可以通
過 ``/proc`` 文件系統獲得,並且可以使用 ``sysctl`` 進行查詢和調整。這些API接
口被描述在Documentation/admin-guide/sysctl/vm.rst文件和 `man 5 proc`_ 中。
.. _man 5 proc: http://man7.org/linux/man-pages/man5/proc.5.html
Linux內存管理有它自己的術語,如果你還不熟悉它,請考慮閱讀下面參考:
Documentation/admin-guide/mm/concepts.rst.
在此目錄下,我們詳細描述瞭如何與Linux內存管理中的各種機制交互。
.. toctree::
:maxdepth: 1
damon/index
ksm
Todolist:
* concepts
* cma_debugfs
* hugetlbpage
* idle_page_tracking
* memory-hotplug
* nommu-mmap
* numa_memory_policy
* numaperf
* pagemap
* soft-dirty
* swap_numa
* transhuge
* userfaultfd
* zswap
@@ -0,0 +1,199 @@
.. include:: ../../disclaimer-zh_TW.rst
:Original: Documentation/admin-guide/mm/ksm.rst
:翻譯:
徐鑫 xu xin <xu.xin16@zte.com.cn>
============
內核同頁合併
============
概述
====
KSM是一種能節省內存的數據去重功能,由CONFIG_KSM=y啓用,並在2.6.32版本時被添
加到Linux內核。詳見 ``mm/ksm.c`` 的實現,以及http://lwn.net/Articles/306704
和https://lwn.net/Articles/330589
KSM最初目的是爲了與KVM(即著名的內核共享內存)一起使用而開發的,通過共享虛擬機
之間的公共數據,將更多虛擬機放入物理內存。但它對於任何會生成多個相同數據實例的
應用程序都是很有用的。
KSM的守護進程ksmd會定期掃描那些已註冊的用戶內存區域,查找內容相同的頁面,這些
頁面可以被單個寫保護頁面替換(如果進程以後想要更新其內容,將自動複製)。使用:
引用:`sysfs intraface <ksm_sysfs>` 接口來配置KSM守護程序在單個過程中所掃描的頁
數以及兩個過程之間的間隔時間。
KSM只合並匿名(私有)頁面,從不合並頁緩存(文件)頁面。KSM的合併頁面最初只能被
鎖定在內核內存中,但現在可以就像其他用戶頁面一樣被換出(但當它們被交換回來時共
享會被破壞: ksmd必須重新發現它們的身份並再次合併)。
以madvise控制KSM
================
KSM僅在特定的地址空間區域時運行,即應用程序通過使用如下所示的madvise(2)系統調
用來請求某塊地址成爲可能的合併候選者的地址空間::
int madvise(addr, length, MADV_MERGEABLE)
應用程序當然也可以通過調用::
int madvise(addr, length, MADV_UNMERGEABLE)
來取消該請求,並恢復爲非共享頁面:此時KSM將去除合併在該範圍內的任何合併頁。注意:
這個去除合併的調用可能突然需要的內存量超過實際可用的內存量-那麼可能會出現EAGAIN
失敗,但更可能會喚醒OOM killer。
如果KSM未被配置到正在運行的內核中,則madvise MADV_MERGEABLE 和 MADV_UNMERGEABLE
的調用只會以EINVAL 失敗。如果正在運行的內核是用CONFIG_KSM=y方式構建的,那麼這些
調用通常會成功:即使KSM守護程序當前沒有運行,MADV_MERGEABLE 仍然會在KSM守護程序
啓動時註冊範圍,即使該範圍不能包含KSM實際可以合併的任何頁面,即使MADV_UNMERGEABLE
應用於從未標記爲MADV_MERGEABLE的範圍。
如果一塊內存區域必須被拆分爲至少一個新的MADV_MERGEABLE區域或MADV_UNMERGEABLE區域,
當該進程將超過 ``vm.max_map_count`` 的設定,則madvise可能返回ENOMEM。(請參閱文檔
Documentation/admin-guide/sysctl/vm.rst)。
與其他madvise調用一樣,它們在用戶地址空間的映射區域上使用:如果指定的範圍包含未
映射的間隙(儘管在中間的映射區域工作),它們將報告ENOMEM,如果沒有足夠的內存用於
內部結構,則可能會因EAGAIN而失敗。
KSM守護進程sysfs接口
====================
KSM守護進程可以由``/sys/kernel/mm/ksm/`` 中的sysfs文件控制,所有人都可以讀取,但
只能由root用戶寫入。各接口解釋如下:
pages_to_scan
ksmd進程進入睡眠前要掃描的頁數。
例如, ``echo 100 > /sys/kernel/mm/ksm/pages_to_scan``
默認值:100(該值被選擇用於演示目的)
sleep_millisecs
ksmd在下次掃描前應休眠多少毫秒
例如, ``echo 20 > /sys/kernel/mm/ksm/sleep_millisecs``
默認值:20(該值被選擇用於演示目的)
merge_across_nodes
指定是否可以合併來自不同NUMA節點的頁面。當設置爲0時,ksm僅合併在物理上位
於同一NUMA節點的內存區域中的頁面。這降低了訪問共享頁面的延遲。在有明顯的
NUMA距離上,具有更多節點的系統可能受益於設置該值爲0時的更低延遲。而對於
需要對內存使用量最小化的較小系統來說,設置該值爲1(默認設置)則可能會受
益於更大共享頁面。在決定使用哪種設置之前,您可能希望比較系統在每種設置下
的性能。 ``merge_across_nodes`` 僅當系統中沒有ksm共享頁面時,才能被更改設
置:首先將接口`run` 設置爲2從而對頁進行去合併,然後在修改
``merge_across_nodes`` 後再將‘run’又設置爲1,以根據新設置來重新合併。
默認值:1(如早期的發佈版本一樣合併跨站點)
run
* 設置爲0可停止ksmd運行,但保留合併頁面,
* 設置爲1可運行ksmd,例如, ``echo 1 > /sys/kernel/mm/ksm/run`` ,
* 設置爲2可停止ksmd運行,並且對所有目前已合併的頁進行去合併,但保留可合併
區域以供下次運行。
默認值:0(必須設置爲1才能激活KSM,除非禁用了CONFIG_SYSFS)
use_zero_pages
指定是否應當特殊處理空頁(即那些僅含zero的已分配頁)。當該值設置爲1時,
空頁與內核零頁合併,而不是像通常情況下那樣空頁自身彼此合併。這可以根據
工作負載的不同,在具有着色零頁的架構上可以提高性能。啓用此設置時應小心,
因爲它可能會降低某些工作負載的KSM性能,比如,當待合併的候選頁面的校驗和
與空頁面的校驗和恰好匹配的時候。此設置可隨時更改,僅對那些更改後再合併
的頁面有效。
默認值:0(如同早期版本的KSM正常表現)
max_page_sharing
單個KSM頁面允許的最大共享站點數。這將強制執行重複數據消除限制,以避免涉
及遍歷共享KSM頁面的虛擬映射的虛擬內存操作的高延遲。最小值爲2,因爲新創
建的KSM頁面將至少有兩個共享者。該值越高,KSM合併內存的速度越快,去重
因子也越高,但是對於任何給定的KSM頁面,虛擬映射的最壞情況遍歷的速度也會
越慢。減慢了這種遍歷速度就意味着在交換、壓縮、NUMA平衡和頁面遷移期間,
某些虛擬內存操作將有更高的延遲,從而降低這些虛擬內存操作調用者的響應能力。
其他任務如果不涉及執行虛擬映射遍歷的VM操作,其任務調度延遲不受此參數的影
響,因爲這些遍歷本身是調度友好的。
stable_node_chains_prune_millisecs
指定KSM檢查特定頁面的元數據的頻率(即那些達到過時信息數據去重限制標準的
頁面)單位是毫秒。較小的毫秒值將以更低的延遲來釋放KSM元數據,但它們將使
ksmd在掃描期間使用更多CPU。如果還沒有一個KSM頁面達到 ``max_page_sharing``
標準,那就沒有什麼用。
KSM與MADV_MERGEABLE的工作有效性體現於 ``/sys/kernel/mm/ksm/`` 路徑下的接口:
pages_shared
表示多少共享頁正在被使用
pages_sharing
表示還有多少站點正在共享這些共享頁,即節省了多少
pages_unshared
表示有多少頁是唯一的,但被反覆檢查以進行合併
pages_volatile
表示有多少頁因變化太快而無法放在tree中
full_scans
表示所有可合併區域已掃描多少次
stable_node_chains
達到 ``max_page_sharing`` 限制的KSM頁數
stable_node_dups
重複的KSM頁數
比值 ``pages_sharing/pages_shared`` 的最大值受限制於 ``max_page_sharing``
的設定。要想增加該比值,則相應地要增加 ``max_page_sharing`` 的值。
監測KSM的收益
=============
KSM可以通過合併相同的頁面來節省內存,但也會消耗額外的內存,因爲它需要生成一些rmap_items
來保存每個掃描頁面的簡要rmap信息。其中有些頁面可能會被合併,但有些頁面在被檢查幾次
後可能無法被合併,這些都是無益的內存消耗。
1) 如何確定KSM在全系統範圍內是節省內存還是消耗內存?這裏有一個簡單的近似計算方法供參考::
general_profit =~ pages_sharing * sizeof(page) - (all_rmap_items) *
sizeof(rmap_item);
其中all_rmap_items可以通過對 ``pages_sharing`` 、 ``pages_shared`` 、 ``pages_unshared``
和 ``pages_volatile`` 的求和而輕鬆獲得。
2) 單一進程中KSM的收益也可以通過以下近似的計算得到::
process_profit =~ ksm_merging_pages * sizeof(page) -
ksm_rmap_items * sizeof(rmap_item).
其中ksm_merging_pages顯示在 ``/proc/<pid>/`` 目錄下,而ksm_rmap_items
顯示在 ``/proc/<pid>/ksm_stat`` 。
從應用的角度來看, ``ksm_rmap_items`` 和 ``ksm_merging_pages`` 的高比例意
味着不好的madvise-applied策略,所以開發者或管理員必須重新考慮如何改變madvis策
略。舉個例子供參考,一個頁面的大小通常是4K,而rmap_item的大小在32位CPU架構上分
別是32B,在64位CPU架構上是64B。所以如果 ``ksm_rmap_items/ksm_merging_pages``
的比例在64位CPU上超過64,或者在32位CPU上超過128,那麼應用程序的madvise策略應
該被放棄,因爲ksm收益大約爲零或負值。
監控KSM事件
===========
在/proc/vmstat中有一些計數器,可以用來監控KSM事件。KSM可能有助於節省內存,這是
一種權衡,因爲它可能會在KSM COW或複製中的交換上遭受延遲。這些事件可以幫助用戶評估
是否或如何使用KSM。例如,如果cow_ksm增加得太快,用戶可以減少madvise(, , MADV_MERGEABLE)
的範圍。
cow_ksm
在每次KSM頁面觸發寫時拷貝(COW)時都會被遞增,當用戶試圖寫入KSM頁面時,
我們必須做一個拷貝。
ksm_swpin_copy
在換入時,每次KSM頁被複制時都會被遞增。請注意,KSM頁在換入時可能會被複
制,因爲do_swap_page()不能做所有的鎖,而需要重組一個跨anon_vma的KSM頁。
--
Izik Eidus,
Hugh Dickins, 2009年11月17日。