Linux 上的 Swappiness 是什麼? (以及如何改變它)

已發表: 2022-01-29
用於計算機的隨機存取存儲器 (RAM) 棒。
subin-ch/Shutterstock.com

Linux swappiness 值與交換開始之前使用了多少 RAM 無關。 這是一個被廣泛報導和普遍認為的錯誤。 我們解釋它到底是什麼。

打破關於 Swapiness 的神話

交換是一種將隨機存取存儲器 (RAM) 中的數據寫入硬盤上的特殊位置(交換分區或交換文件)以釋放 RAM 的技術。

Linux 有一個稱為 swappiness 值的設置。 關於此設置控制的內容有很多混淆。 對 swappiness 最常見的錯誤描述是它為 RAM 使用設置了一個閾值,當使用的 RAM 量達到該閾值時,交換開始。

這是一個經常被重複的誤解,以至於現在它被認為是智慧。 如果(幾乎)其他人都告訴你這正是swappiness的運作方式,那麼當我們說它不是時你為什麼要相信我們呢?

簡單的。 我們將證明這一點。

您的 RAM 分為多個區域

Linux 並不認為您的 RAM 是一個大的同質內存池。 它認為它被劃分為許多不同的區域,稱為區域。 您的計算機上存在哪些區域取決於它是 32 位還是 64 位。 以下是 x86 架構計算機上可能區域的簡化描述。

  • 直接內存訪問 (DMA) :這是低 16 MB 內存。 該區域之所以得名,是因為很久以前,有些計算機只能直接訪問該物理內存區域。
  • 直接內存訪問 32 :儘管它的名字,直接內存訪問 32 (DMA32) 是一個僅在 64 位 Linux 中發現的區域。 這是低 4 GB 的內存。 在 32 位計算機上運行的 Linux 只能對這個數量的 RAM 執行 DMA(除非它們使用物理地址擴展 (PAE) 內核),這就是該區域的名稱。 雖然,在 32 位計算機上,它被稱為 HighMem。
  • 正常:在 64 位計算機上,正常內存是 4GB 以上的所有 RAM(大約)。 在 32 位機器上,它是介於 16 MB 和 896 MB 之間的 RAM。
  • HighMem :這只存在於 32 位 Linux 計算機上。 它是 896 MB 以上的所有 RAM,包括在足夠大的機器上超過 4 GB 的 RAM。

頁大小值

RAM 以固定大小的頁面分配。 該大小由內核在啟動時通過檢測計算機的體系結構來確定。 通常,Linux 計算機上的頁面大小為 4 KB。

廣告

您可以使用getconf命令查看頁面大小:

 獲取配置頁面大小

獲取配置頁面大小

區域附加到節點

區域附加到節點。 節點與中央處理單元 (CPU) 相關聯。 內核將嘗試從與該 CPU 關聯的節點​​為在該 CPU 上運行的進程分配內存。

將節點綁定到 CPU 的概念允許使用非統一內存訪問架構將混合內存類型安裝在專業的多 CPU 計算機中。

這都是非常高端的。 普通的 Linux 計算機將有一個節點,稱為節點零。 所有區域都將屬於該節點。 要查看計算機中的節點和區域,請查看/proc/buddyinfo文件。 我們將使用less來做到這一點:

 少 /proc/buddyinfo 

這是本文研究的 64 位計算機的輸出:

 節點 0,區域 DMA 1 1 1 0 2 1 1 0 1 1 3
節點 0,區域 DMA32 2 67 58 19 8 3 3 1 1 1 17
廣告

有一個節點,節點零。 這台計算機只有 2 GB 的 RAM,因此沒有“正常”區域。 只有兩個區域,DMA 和 DMA32。

每列代表一定大小的可用頁面數。 例如,對於 DMA32 區域,從左側讀取:

  • 2 :有 2 個 ^( 0 *PAGESIZE) 個內存塊。
  • 67 :有 2^( 1 *PAGE_SIZE) 個內存塊中的 67 個。
  • 58 :有 2^( 2 *PAGESIZE) 個可用內存塊中的 58 個。
  • 以此類推,一直到……
  • 17 :有 17 個 2^( 512 *PAGESIZE) 塊。

但實際上,我們查看此信息的唯一原因是查看節點和區域之間的關係。

文件頁面和匿名頁面

內存映射使用頁表條目集來記錄使用了哪些內存頁以及用於什麼目的。

內存映射可以是:

  • 文件支持:文件支持的映射包含從文件中讀取的數據。 它可以是任何類型的文件。 需要注意的重要一點是,如果系統釋放了此內存並需要再次獲取該數據,則可以再次從文件中讀取它。 但是,如果內存中的數據已更改,則需要將這些更改寫入硬盤驅動器上的文件,然後才能釋放內存。 如果這沒有發生,更改將丟失。
  • 匿名:匿名內存是沒有文件或設備支持的內存映射。 這些頁面可能包含程序即時請求的內存以保存數據,或者用於堆棧和堆等內容。 因為這類數據背後沒有文件,所以必須專門留出一個地方來存放匿名數據。 那個地方就是交換分區或交換文件。 在釋放匿名頁面之前將匿名數據寫入交換。
  • 設備支持:設備通過塊設備文件尋址,這些文件可以被視為文件。 可以從它們讀取數據並寫入它們。 設備支持的內存映射具有存儲在其中的設備的數據。
  • Shared :多個頁表條目可以映射到 RAM 的同一頁。 通過任何映射訪問內存位置將顯示相同的數據。 通過更改這些共同監視的內存位置中的數據,不同的進程可以以非常有效的方式相互通信。 共享可寫映射是實現高性能進程間通信的常用方法。
  • 寫時復制:寫時復制是一種惰性分配技術。 如果請求已在內存中的資源的副本,則通過返回到原始資源的映射來滿足請求。 如果“共享”資源的進程之一試圖寫入它,則必須在內存中真正複製資源,以允許對新副本進行更改。 所以內存分配只發生在第一個寫命令上。

對於交換性,我們只需要關注列表中的前兩個:文件頁面和匿名頁面。

交換性

以下是 GitHub 上 Linux 文檔中對 swappiness 的描述:

廣告

"This control is used to define how aggressive (sic) the kernel will swap memory pages. Higher values will increase aggressiveness, lower values decrease the amount of swap. A value of 0 instructs the kernel not to initiate swap until the amount of free and file-backed pages is less than the high water mark in a zone.

The default value is 60."

這聽起來像是交換強度使交換強度上升或下降。 有趣的是,它指出將 swappiness 設置為零並不會關閉交換。 它指示內核在滿足某些條件之前不要交換。 但是交換仍然可能發生。

讓我們深入挖掘。 下面是內核源代碼文件 vmscan.c 中vm_swappiness的定義和默認值:

/*
* From 0 .. 100. Higher means more swappy.
*/
int vm_swappiness = 60;

swappiness 值的範圍可以從 0 到 100。同樣,評論聽起來確實像 swappiness 值與發生多少交換有關,更高的數字會導致更多的交換。

在源代碼文件中,我們可以看到一個名為swappiness的新變量被分配了一個值,該值由函數mem_cgroup_swappiness()返回。 對源代碼進行更多跟踪將顯示此函數返回的值是vm_swappiness 。 所以現在,變量swappiness設置為等於vm_swappiness設置的任何值。

int swappiness = mem_cgroup_swappiness(memcg);

廣告

在同一個源代碼文件中再往下一點,我們看到:

/*
* With swappiness at 100, anonymous and file have the same priority.
* This scanning priority is essentially the inverse of IO cost.
*/
anon_prio = swappiness;
file_prio = 200 - anon_prio;

那很有意思。 兩個不同的值來自swappinessanon_priofile_prio變量保存這些值。 隨著一個增加,另一個減少,反之亦然

Linux swappiness 值實際上設置了兩個值之間的比率

黃金比例

文件頁保存的數據可以在釋放內存時輕鬆檢索。 Linux 可以再次讀取該文件。 如我們所見,如果文件數據在 RAM 中已更改,則必須先將這些更改寫入文件,然後才能釋放文件頁面。 但是,無論哪種方式,都可以通過從文件中讀取數據來重新填充 RAM 中的文件頁面。 那麼,為什麼還要麻煩將這些頁面添加到交換分區或交換文件中呢? 如果您再次需要該數據,您不妨從原始文件中讀回它,而不是交換空間中的冗余副本。 所以文件頁面不存儲在交換中。 它們被“存儲”回原始文件中。

對於匿名頁面,沒有與內存中的值關聯的基礎文件。 這些頁面中的值是動態得出的。 您不能簡單地從文件中讀回它們。 可以恢復匿名頁面內存值的唯一方法是在釋放內存之前將數據存儲在某處。 這就是交換所持有的。 您將需要再次引用的匿名頁面。

廣告

但請注意,對於文件頁面和匿名頁面,釋放內存可能需要硬盤寫入。 如果文件頁面數據或匿名頁面數據自上次寫入文件或交換後已更改,則需要文件系統寫入。 要檢索數據,需要讀取文件系統。 這兩種類型的頁面回收都是昂貴的。 試圖通過最小化匿名頁面的交換來減少硬盤驅動器的輸入和輸出只會增加處理寫入和讀取文件的文件頁面所需的硬盤驅動器輸入和輸出量。

從最後的代碼片段可以看出,有兩個變量。 一個稱為file_prio表示“文件優先級”,另一個稱為anon_prio表示“匿名優先級”。

  • anon_prio變量設置為 Linux swappiness 值。
  • file_prio值設置為 200 減去anon_prio值。

這些變量包含協同工作的值。 如果它們都設置為 100,則它們是相等的。 對於任何其他值, anon_prio將從 100 減少到 0,而file_prio將從 100 增加到 200。這兩個值會輸入一個複雜的算法,該算法確定 Linux 內核是否以回收(釋放)文件頁面或匿名的偏好運行頁。

您可以將file_prio視為系統釋放文件頁面的意願,而將anon_prio視為系統釋放匿名頁面的意願。 這些值不做的是為何使用交換設置任何類型的觸發器或閾值。 這是其他地方決定的。

但是,當需要釋放內存時,回收和交換算法會考慮這兩個變量以及它們之間的比率,以確定優先考慮釋放哪些頁麵類型。 這決定了相關的硬盤活動是處理文件頁面的文件還是處理匿名頁面的交換空間。

什麼時候交換實際切入?

我們已經確定 Linux swappiness 值設置了對將被掃描以進行潛在回收的內存頁麵類型的首選項。 這很好,但是必須決定什麼時候交換會介入。

廣告

每個內存區域都有一個高水位線和一個低水位線。 這些是系統派生值。 它們是每個區域中 RAM 的百分比。 正是這些值用作交換觸發閾值。

要檢查您的高水位線和低水位線,請使用以下命令查看/proc/zoneinfo文件:

 少 /proc/zoneinfo 

每個區域都有一組以頁為單位的內存值。 以下是測試機器上 DMA32 區域的值。 低水位線是 13966 頁,高水位線是 16759 頁:

  • 在正常運行條件下,當區域中的可用內存降至區域的低水位線以下時,交換算法開始掃描內存頁面以尋找可以回收的內存,同時考慮anon_priofile_prio的相對值。
  • 如果 Linux swappiness 值設置為零,則當文件頁面和空閒頁面的組合值小於高水位線時會發生交換。

所以你可以看到你不能使用 Linux swappiness 值來影響交換在 RAM 使用方面的行為。 它只是不能那樣工作。

Swapiness應該設置為什麼?

這取決於硬件、工作負載、硬盤類型以及您的計算機是台式機還是服務器。 顯然,這不會是一種適合所有類型的設置。

而且您必須記住,交換不僅用作在內存空間不足時釋放 RAM 的機制。 交換是運行良好的系統的重要組成部分,沒有它,Linux 很難實現健全的內存管理。

廣告

更改 Linux swappiness 值會立竿見影; 你不需要重新啟動。 因此,您可以進行小的調整併監控效果。 理想情況下,您會在幾天內執行此操作,並在您的計算機上進行不同類型的活動,以嘗試找到最接近理想設置的設置。

這些是需要考慮的幾點:

  • 通過將 Linux swappiness 值設置為零來嘗試“禁用交換”只是將交換相關的硬盤驅動器活動轉移到文件相關的硬盤驅動器活動。
  • 如果您有老化的機械硬盤驅動器,您可以嘗試降低 Linux 的 swappiness 值以遠離匿名頁面回收並減少交換分區流失。 當然,當您調低一個設置時,另一個設置會增加。 減少交換流失可能會增加文件系統流失。 但是您的計算機可能更願意選擇一種方法而不是另一種方法。 真的,唯一確定的方法就是嘗試看看。
  • 對於單一用途的服務器,例如數據庫服務器,您可以從數據庫軟件供應商處獲得指導。 很多時候,這些應用程序都有自己專門設計的文件緩存和內存管理例程,您最好依賴這些例程。 軟件提供商可能會根據機器規格和工作負載建議 Linux 交換值。
  • 對於擁有相當新硬件的普通桌面用戶? 保持原狀。

如何設置 Linux Swappiness 值

在你改變你的 swappiness 值之前,你需要知道它的當前值是多少。 如果你想減少一點,問題是比什麼少一點? 您可以使用以下命令查找:

 貓 /proc/sys/vm/swappiness 

貓 /proc/sys/vm/swappiness

要配置 swappiness 值,請使用sysctl命令:

 sudo sysctl vm.swappiness=45 

新值立即使用,無需重新啟動。

事實上,如果您重新啟動,swappiness 值將返回到其默認值 60。當您完成試驗並決定要使用的新值時,您可以通過將其添加到/etc/sysctl.conf來使其在重新啟動後保持不變/etc/sysctl.conf文件。 您可以使用您喜歡的任何編輯器。 使用以下命令使用nano編輯器編輯文件:

 須藤納米 /etc/sysctl.conf 

nano打開時,滾動到文件底部並添加這一行。 我們使用 35 作為永久交換值。 您應該替換您希望使用的值。

 vm.swappiness=35 

要保存更改並退出nano ,請按“Ctrl+O”,按“Enter”,然後按“Ctrl+Z”。

內存管理很複雜

內存管理很複雜。 這就是為什麼對於普通用戶來說,最好把它留給內核。

廣告

很容易認為您使用的 RAM 比實際更多。 像topfree這樣的實用程序可能會給人錯誤的印象。 Linux 會將空閒 RAM 用於各種用途,例如磁盤緩存。 這人為地提高了“已用”內存數字並降低了“空閒”內存數字。 實際上,用作磁盤緩存的 RAM 被標記為“已使用”和“可用”,因為它可以隨時回收,而且速度非常快。

對於外行來說,可能看起來交換不起作用,或者交換值需要更改。

一如既往,魔鬼在細節中。 或者,在這種情況下,是守護進程。 內核交換守護進程。

相關:適合開發人員和愛好者的最佳 Linux 筆記本電腦