Windows 10 中的記憶體/提交費用如何運作?

Windows 10 中的記憶體/提交費用如何運作?

這個問題是由以下經常觀察到的現象引起的,我想找到解釋:

  1. 目前提交通常高於實體使用量 + 頁面檔案大小。那是怎麼回事?這不是不可能嗎? [這似乎可能是由於壓縮造成的。這將問題轉化為:為什麼不提交限制然後上漲或其他什麼?也就是說,如果壓縮對記憶體使用沒有幫助,那麼壓縮還有什麼意義呢?
  2. 有時,這會達到極端水平,其中當前提交是實體記憶體使用量的兩倍以上!
  3. 當提交費用填滿並且 Windows 開始要求我關閉東西時,大多數時候實體記憶體都在 60% 左右。這看起來效率極低。

正如 Process Explorer 所報告的,這是在 Windows 10 上。

我想回答的最終問題是:我是否可以放棄人為地膨脹我的頁面文件,以達到我的空間匱乏的 SSD 無法處理的水平,以便我可以真正有效地利用我的物理內存? (或者即使它不是那麼完整。也就是說,我想避免像“對頁面文件執行 X/Y/Z”之類的建議。)

答案1

一旦您了解提交費用僅代表潛在的- 然而“如果需要的話保證可用” - 使用虛擬內存,而“私有工作集” - 本質上是“提交”內存使用的 RAM - 是實際的使用,就像頁面文件空間一樣。 (但這並不是RAM的全部使用,因為還有其他東西使用RAM)。

假設我們討論的是 32 位元系統,因此每個進程可用的最大虛擬位址空間通常為 2 GiB。 (沒有本質區別任何以下內容適用於 64 位元系統,除了位址和大小可以更大 - 大得多。

現在假設進程中運行的程式使用 VirtualAlloc(Win32 API)「提交」2 MiB 虛擬記憶體。正如您所期望的,這將顯示為額外的 2 MiB 提交費用,並且在進程中可供將來分配的虛擬位址空間位元組數減少了 2 MiB。

但它實際上還不會使用任何實體記憶體(RAM)!

VirtualAlloc 呼叫將向呼叫者傳回已分配區域的起始位址;該區域將位於 0x10000 到 0x7FFEFFFF 範圍內,約 2 GiB。 (每個進程中 vas 的第一個和最後一個 64KiB,或十六進位的 0x10000 永遠不會被分配。)

但同樣 - 沒有實際物理使用 2 MiB貯存然而!不在 RAM 中,甚至不在頁面檔案中。 (有一個稱為「虛擬位址描述符」的微小結構,它描述了私有提交區域的起始 va 和長度。)

所以你有它!提交費用增加了,但實體記憶體使用量沒有增加。

使用 sysinternals 工具可以輕鬆演示這一點testlimit

稍後,假設程式在該區域(無論在哪裡)儲存了某些內容(即記憶體寫入操作)。在該區域下還沒有任何物理內存,因此這樣的訪問將導致頁面錯誤。作為回應,作業系統的記憶體管理器,特別是頁面錯誤處理程序例程(簡稱「尋呼機」......它稱為 MmAccessFault)將:

  1. 分配先前「可用」的實體頁
  2. 為被存取的虛擬頁設定頁表條目,以將虛擬頁號與新指派的實體頁號關聯起來
  3. 將實體頁新增至進程私有工作集
  4. 並消除頁面錯誤,導致重試引發錯誤的指令。

您現在已將一頁(4 KiB)“錯誤”到該過程中。實體記憶體使用量將相應增加,「可用」RAM 將減少。承諾費用不變。

稍後,如果該頁面有一段時間沒有被引用並且對 RAM 的需求很高,則可能會發生這種情況:

  1. 作業系統從進程工作集中刪除該頁面。
  2. 因為它是在被帶入工作集中後被寫入的,所以它被放入修改頁列表中(否則它將進入備用頁列表)。頁表項仍然反映 RAM 頁面的實體頁號,但現在其「有效」位元已清除,因此下次引用它時將發生頁錯誤
  3. 當修改的頁面清單達到一個小閾值時,修改頁面編寫器「系統」進程中的執行緒喚醒並將修改後的頁面內容儲存到頁面檔案中(假設您有一個),並且...
  4. 將這些頁面從修改清單中刪除並將它們放入備用清單中。現在它們被視為「可用」RAM 的一部分;但目前它們仍然保留著各自流程中的原始內容。同樣,提交費用不會改變,但 RAM 使用量和進程專用工作集會下降。
  5. 備用清單上的頁面現在可以改變用途,也就是說用於其他用途 - 例如解決系統上任何進程的頁面錯誤,或由 SuperFetch 使用。然而...
  6. 如果在修改或備用清單中遺失頁面的進程在重新調整實體頁面的用途(即仍具有其原始內容)之前嘗試再次存取該頁面,則無需從磁碟讀取即可解決頁面錯誤。該頁面只是被放回進程工作集中,並且頁表條目被設定為「有效」。這是“軟”或“廉價”頁面錯誤的範例。我們說備用清單和修改清單形成了可能很快再次需要的頁面的系統範圍快取。

如果您沒有頁面文件,則步驟 3 到 5 變更為:

  1. 這些頁面位於已修改的清單上,因為沒有地方可以寫入其內容。

  2. 這些頁面位於已修改的清單上,因為沒有地方可以寫入其內容。

  3. 這些頁面位於已修改的清單上,因為沒有地方可以寫入其內容。

步驟 6 保持不變,因為修改清單上的頁面可以作為「軟」頁面錯誤返回到遺失它們的進程中。但是,如果沒有發生這種情況,頁面將保留在已修改的清單上,直到進程釋放相應的虛擬記憶體(可能是因為進程結束)。

除了私有提交記憶體之外,虛擬位址空間和 RAM 還可以有其他用途。有映射的虛擬位址空間,其後備儲存是某個指定的檔案而非頁面檔案。分頁的映射 vas 頁面反映在 RAM 使用情況中,但映射記憶體不會影響提交費用,因為映射檔案提供後備儲存:不在 RAM 中的映射區域的任何部分都簡單地保存在映射檔案。另一個區別是大多數文件映射可以在進程之間共享;一個進程記憶體中已經存在的共享頁面可以添加到另一個進程中,而無需再次存取磁碟(另一種軟頁面錯誤)。

並且有不可分頁的vas,沒有後備存儲,因為它始終駐留在 RAM 中。這既有助於報告的 RAM 使用情況,也有助於「提交費用」。

這似乎可能是由於壓縮造成的。這將問題轉化為:為什麼不提交限制然後上漲或其他什麼?也就是說,如果壓縮對記憶體使用沒有幫助,那麼它還有什麼意義呢?

不,它與壓縮無關。 Windows 中的記憶體壓縮是作為中間步驟在本來會寫入頁面檔案的頁面上完成的。實際上它允許修改後的頁面列表使用較少的 RAM 來容納更多的內容,雖然會消耗一定的 CPU 時間,但速度比頁面檔案 I/O(甚至對於 SSD)快得多。由於提交限制的計算公式為全部的RAM + 頁面檔案大小,而不是 RAM 使用量 + 頁面檔案使用量,不會影響提交限制。提交限制不會隨著正在使用的 RAM 數量或用途而改變。

當提交費用填滿並且 Windows 開始要求我關閉東西時,大多數時候實體記憶體都在 60% 左右。這看起來效率極低。

這並不是說 Windows 效率低。這是您正在運行的應用程式。他們投入的瓦斯比實際使用的要多得多。

整個「提交費用」和「提交限制」機制的原因是這樣的:當我呼叫 VirtualAlloc 時,我應該檢查返回值以查看它是否非零。如果它為零,則表示我的分配嘗試失敗,可能是因為它會導致提交費用超出提交限制。我應該做一些合理的事情,例如嘗試減少提交,或乾淨地退出程序。

如果 VirtualAlloc 返回非零,即一個地址,這告訴我係統已經做出保證 - 一個承諾,如果你願意的話 - 無論我要求多少字節,從該地址開始,如果我選擇訪問它們,則可用;有一個地方可以放置所有內容 - RAM 或頁面檔案。即,沒有理由預期在存取該區域內的任何內容時會出現任何類型的失敗。這很好,因為期望我檢查“它有效嗎?”是不合理的。每次訪問分配的區域時。

「現金借貸銀行」的比喻

它有點像銀行提供信貸,但嚴格以庫存現金為基礎。 (當然,這不是真正的銀行的運作方式。)

假設銀行一開始手上有一百萬美元現金。人們到銀行申請不同金額的信用額度。假設銀行批准我 10 萬美元的信貸額度(我創建了一個私人承諾區域);這並不意味著任何現金實際上已離開金庫。如果我後來真的申請了一筆貸款,比如說 20,000 美元(我訪問了該地區的一個子集),這確實會從銀行中扣除現金。

但無論我是否申請任何貸款,我已獲得最多 10 萬美元的批准這一事實意味著銀行隨後只能為其所有客戶批准另外價值 90 萬美元的信貸額度。銀行不會批准超過其現金儲備的信貸(即它不會過度使用他們),因為這意味著當先前批准的借款人後來出現打算取出時,銀行可能不得不拒絕他們他們的貸款。這將是非常糟糕的,因為銀行已經堅定的如果允許這些貸款,銀行的聲譽就會直線下降。

是的,就銀行使用現金而言,這是「低效的」。客戶核准的信貸額度與實際貸款金額之間的差距越大,效率就越低。但效率低落並不是銀行的錯;而是銀行的錯。要求如此高的信用額度卻只辦理小額貸款,這是客戶的「錯」。

該銀行的商業模式是,當先前批准的借款人前來獲取貸款時,它根本無法拒絕他們——這樣做對客戶來說將是「致命的」。這就是為什麼銀行會仔細追蹤有多少貸款資金已「承諾」。

我認為擴展頁面文件或添加另一個頁面文件就像銀行出去獲取更多現金並將其添加到貸款基金中一樣。

如果您想在這個類比中對映射和不可分頁記憶體進行建模...不可分頁就像一筆小額貸款,您需要在開戶時取出並保留在其中。 (定義每個新進程的不可分頁結構。)映射記憶體就像攜帶您自己的現金(正在映射的文件)並將其存入銀行,然後一次僅取出其中的一部分(將其分頁)。為什麼不立即將其全部分頁呢?我不知道,也許你的錢包裡沒有足夠的空間存放那麼多現金。 :) 這不會影響別人借錢,因為你存入的現金是在你自己的帳戶上,而不是一般的貸款資金。這個類比從這裡開始就不成立了,特別是當我們開始考慮共享記憶體時,所以不要把它推得太遠。

回到 Windows 作業系統:您擁有大量「可用」RAM 的事實與提交費用和提交限制無關。如果您接近提交限制,則表示作業系統已經提交 - 即 承諾提供當被要求時 - 那麼多儲存空間。不必全部使用完畢即可執行限制。

我是否可以放棄人為地將我的頁面文件膨脹到我的 SSD 空間不足而無法處理的水平,以便我可以真正有效地利用我的物理內存? (或者即使它不是那麼完整。也就是說,我想避免像“對頁面文件執行 X/Y/Z”之類的建議。)

好吧,很抱歉,但是如果您遇到了提交限制,您可以做三件事:

  1. 增加內存。
  2. 增加頁面檔案大小。
  3. 一次運行更少的東西。

關於選項 2:您可以將第二個頁面檔案放在硬碟上。如果應用程式實際上並沒有使用所有提交的記憶體(顯然它們沒有使用,因為您看到瞭如此多的可用RAM),那麼您實際上不會太多地訪問該頁面文件,因此將其放在硬碟上不會損害性能。如果硬碟的緩慢仍然困擾著您,另一種選擇是購買一個較小且便宜的第二個 SSD,並將第二個頁面檔案放在上面。一個「阻礙」將是一台無法增加第二個「不可移動」驅動器的筆記型電腦。 (Windows 不允許您將頁面檔案放在可移動磁碟機上,就像透過 USB 連接的任何磁碟機一樣。)

這是我寫的另一個答案這從不同的方向解釋了事情。

ps:您詢問了 Windows 10,但我應該告訴您,它在 NT 系列的每個版本中都以相同的方式工作,回到 NT 3.1,以及預發布版本。可能發生變化的是 Windows 頁面檔案大小的預設設置,從 1.5 倍或 1 倍 RAM 大小變得更小。我相信這是一個錯誤。

相關內容