“記憶體”記憶體實際上是免費的嗎?
執行時
cat /proc/meminfo
,您會在頂部獲得以下 3 個值:MemTotal: 6291456 kB MemFree: 4038976 kB Cached: 1477948 kB
據我所知,“Cached”值是由 Linux 系統創建的磁碟記憶體,如果任何應用程序需要更多 RAM,它將立即釋放,因此 Linux 永遠不會耗盡記憶體,直到 MemFree 和 Cached 都為零。
不幸的是,/proc/meminfo 沒有報告“MemAvailable”,可能是因為它在虛擬伺服器中執行。(核心版本為 4.4)
因此,出於所有實際目的,可用於應用程序的 RAM 是 MemFree + Cached。
這種觀點正確嗎?
在許多現實世界的案例中,這種觀點可能會產生很大的誤導。
核心現在提供了
MemAvailable
現場可用記憶體的估計。該值與 顯著不同MemFree + Cached
。$$ kernel change description, 2014 $$ 許多負載平衡和工作負載放置程序檢查 /proc/meminfo 以估計有多少可用記憶體。他們通常通過將“免費”和“記憶體”相加來做到這一點,十年前這很好,但今天幾乎可以保證是錯誤的。
這是錯誤的,因為 Cached 包含不可作為頁面記憶體釋放的記憶體,例如共享記憶體段、tmpfs 和 ramfs,並且它不包括可回收的slab 記憶體,後者在大多數空閒系統上會佔用很大一部分系統記憶體很多文件。
目前,可以從 MemFree、Active(file)、Inactive(file) 和 SReclaimable 以及來自 /過程/區域資訊。但是,這在未來可能會發生變化,並且真的不應該期望使用者空間知道核心內部來估計可用記憶體量。在 /proc/meminfo 中提供這樣的估計會更方便。如果將來事情發生變化,我們只需在一個地方進行更改。
…
Documentation/filesystems/proc.txt:
…
MemAvailable:估計有多少記憶體可用於啟動新應用程序,無需交換。根據 MemFree、SReclaimable、文件 LRU 列表的大小以及每個區域中的低水位線計算得出。該估計考慮到系統需要一些頁面記憶體才能正常執行,並且由於項目正在使用,並非所有可回收的slab都是可回收的。這些因素的影響因係統而異。
- MemA可用的詳細資訊
正如上面所說,tmpfs 和其他
Shmem
記憶體不能被釋放,只能移動到交換。 由於包含此可交換記憶體,因此Cached
in/proc/meminfo
可能非常具有誤導性。Shmem
如果 tmpfs 中有太多文件,它可能會佔用大量記憶體 :-)。Shmem
還可以包括一些圖形記憶體分配,這可能非常大。
MemAvailable
故意不包括可交換記憶體。交換過多會導致長時間的延遲。您甚至可能選擇在沒有交換空間的情況下執行,或者只允許相對有限的數量。我不得不仔細檢查是如何
MemAvailable
工作的。乍一看,程式碼似乎沒有提到這個區別。/* * Not all the page cache can be freed, otherwise the system will * start swapping. Assume at least half of the page cache, or the * low watermark worth of cache, needs to stay. */ pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE]; pagecache -= min(pagecache / 2, wmark_low); available += pagecache;
但是,我發現它正確地被視為
Shmem
“使用過的”記憶體。我在 tmpfs 中創建了幾個 1GB 的文件。每增加 1GBShmem
減少MemAvailable
1GB。所以“文件 LRU 列表”的大小不包括共享記憶體或任何其他可交換記憶體。(我注意到計算“臟限制”的程式碼中也使用了這些相同的頁數)。此
MemAvailable
計算還假設您希望至少保留足夠的文件記憶體以等於核心的“低水位線”。或目前記憶體的一半 - 以較小者為準。(它也對可回收板做出相同的假設)。核心的“低水位”可以調整,但通常是系統 RAM 的 2% 左右。所以如果你只想要一個粗略的估計,你可以忽略這部分:-)。當您
firefox
在頁面記憶體中映射大約 100MB 的程式碼執行時,您通常希望將這 100MB 保留在 RAM 中:-)。否則,充其量您將遭受延遲,最壞的情況是系統將花費所有時間在不同的應用程序之間顛簸。因此MemAvailable
,為此允許一小部分 RAM。它可能不夠,或者可能過於慷慨。“這些因素的影響因係統而異”。對於許多 PC 工作負載,“大量文件”這一點可能並不重要。即便如此,我的筆記型電腦上目前有 500MB 可回收的平板記憶體(8GB RAM)。這是由於
ext4_inode_cache
(超過 300K 個對象)。發生這種情況是因為我最近不得不掃描整個文件系統,以查找正在使用我的磁碟空間的內容:-)。我使用了命令df -x / | sort -n
,但例如 Gnome Disk Usage Analyzer 會做同樣的事情。2.$$ edit $$對照組的記憶
所謂的“Linux 容器”是由
namespaces
、cgroups
和各種其他特性建構而成的 :-)。它們可能會提供一個足夠令人信服的環境來執行幾乎類似於完整 Linux 系統的東西。託管服務可以像這樣建構容器並將它們作為“虛擬伺服器”出售:-)。託管伺服器還可以使用主線 Linux 中沒有的功能建構“虛擬伺服器”。 OpenVZ容器比主線 cgroup 早兩年,並且可以使用“beancounters”來限制記憶體。因此,如果您只閱讀文件或詢問有關主線 Linux 核心的問題,您將無法準確理解這些記憶體限制是如何工作的。
cat /proc/user_beancounters
顯示目前使用情況和限制。vzubc
以稍微友好的格式呈現它。beancounters的首頁記錄了行名。控制組包括對其中的程序設置記憶體限制的能力。如果您在這樣的 cgroup 中執行應用程序,則並非所有系統記憶體都可供應用程序使用:-)。那麼,我們如何才能看到這種情況下的可用記憶體呢?
這個介面在很多方面有所不同,具體取決於您使用的是cgroup-v1還是cgroup-v2。
我的筆記型電腦安裝使用 cgroup-v1。我可以跑
cat /sys/fs/cgroup/memory/memory.stat
。該文件顯示各種欄位,包括total_rss
、total_cache
、total_shmem
。shmem,包括 tmpfs,計入記憶體限制。我想您可以將total_rss
其視為 的逆等價物MemFree
。還有文件memory.kmem.usage_in_bytes
,代表核心記憶體,包括平板。(我假設memory.kmem.
還包括memory.kmem.tcp.
和任何未來的擴展,儘管這沒有明確記錄)。沒有單獨的計數器來查看可回收的平板記憶體。cgroup-v1 的文件說達到記憶體限制不會觸發任何slab 記憶體的回收。(該文件還有一個免責聲明,說它“已經過時了”,您應該檢查目前的原始碼)。cgroup-v2 不同。我認為根(頂級)cgroup 不支持記憶體記帳。cgroup-v2 仍然有一個
memory.stat
文件。所有欄位匯總在子 cgroup 上,因此您無需查找total_...
欄位。有一個file
欄位,這意味著同樣的事情cache
。惱人的是,我看不到像rss
裡面這樣的整體領域memory.stat
;我想您將不得不添加各個欄位。可回收和不可回收的平板記憶體有單獨的統計資訊;我認為 v2 cgroup 旨在在記憶體開始不足時回收平板。Linux cgroups 不會自動虛擬化
/proc/meminfo
(或 中的任何其他文件/proc
),因此會顯示整個機器的值。這會使 VPS 客戶感到困惑。但是,可以使用名稱空間來替換特定容器軟體偽造/proc/meminfo
的文件。假值的有用程度取決於特定軟體的功能。
systemd
相信 cgroup-v1 不能安全地委託給容器。我查看了systemd-nspawn
我的 cgroup-v1 系統上的一個容器。我可以看到它被放置在裡面的 cgroup,以及它的記憶體統計。另一方面,包含systemd
沒有為資源記帳設置通常的每服務 cgroup。如果此 cgroup 中未啟用記憶體記帳,我認為容器將無法啟用它。我假設如果你在一個 cgroup-v2 容器中,它看起來與真正的 cgroup-v2 系統的根不同,你將能夠看到它的頂級 cgroup 的記憶體佔。或者,如果您可以看到的 cgroup 沒有啟用記憶體記帳,希望您將獲得授權,以便您可以在(或等效)中啟用記憶體記帳。
systemd