Skip to main content

windows系統的記憶體用量指標

Opass
A life well lived

最近看到同事在抓漏,但是觀察Memory的指標是Working Set,這是有些問題的,於是花了點時間整理Windows的記憶體指標。Memory大概是Windows系統上最模糊的用詞之一,整理這篇文章順便釐清自己一些疑惑。

Page files

大家都知道Windows上當實體記憶體不足時,會把一些比較不常用的記憶體內容置換到硬碟上先暫存起來,稱之為虛擬記憶體(virtual memory也是個很多義的詞),這個過程稱之為Pageout,存放的檔案叫做Page files。 注意到我用了複數(page files),Windows系統上的Page files可以有0~16個。Page files的功能是儲存那些因為系統記憶體需求的壓力而需要被放到硬碟上的記憶體分頁。

Page files的所在位置可以通過註冊表查詢,或是透過(Win10) 本機=>內容=>進階系統設定=>進階=>效能=>設定=>進階=>虛擬記憶體,進行設定。 根據系統不同,Page files有不同的大小限制,x86最大可以到4095MB,x64或PAE後的系統可以到16TB,IA64可以到32TB。Page files一旦被打開使用後,就沒辦法刪除。因此在系統啟動的狀態下,Page files是無法進行磁碟重組的。

Page file可以在系統關機後繼續以硬碟的形式存在在檔案中,但可能會造成安全性上的問題。 Page files的大小一般來說min~max大概在1~3倍RAM之間,也可能會因為系統設定而不在該範圍內。

Commit Charge

我們知道系統有兩種記憶體資源,一種是RAM,另一種是page files。

Commit Charge指的是系統承諾一定會在RAM或page files保留空間的記憶體數量。這裡有點抽象,我解釋一下我對Commit Charge的理解。

某些記憶體的內容,系統並不需要保證「這些內容一定要留在RAM上或page files上」。像是mapping到dll檔的記憶體區塊。當然實際執行時,還是要把這些dll的內容找一塊實體記憶體load上去供程式載入,但拋棄掉這塊記憶體上的內容,之後需要時再從檔案載入回來也行。我們可以說,這種記憶體區塊的內容,他們有associated files作為backing store。Commit Charge指的是那些一定要留在RAM或paging files上的內容,因為這些東西一定得在系統上找個地方放。

順帶一題,Commit Charge的值和實際的記憶體使用量是兩回事。系統承諾會替你保留這段空間,但是你現在並不見得會用到這空間,Lazy是好事,因此實際記憶體的用量會小於所承諾的空間。

系統能承諾的Commit Charge,其大小限制就是RAM + page files的大小。如果Page files可以調大,那麼該限制也會跟著被放寬。如果process持續無限制的索求記憶體,導致系統沒辦法承諾給予,當然就會fail。 以下情況會導致Commit Charge增加,另外可以注意一個指標叫做page file quota(其實就是Private Bytes),每個process都有這個指標,大部分情況下,process page file quota會和commit charge一同增加。

  • 當Process透過VisualAlloc call with COMMIT option的時候,代表Process要系統承諾記憶體。這個值也會加入process page quota。這是最常見的情況了。
  • 注意Commit和Reserved不一樣,VisualAlloc一塊Reserved的記憶體,只是代表我想預訂這一段範圍的virtual memory,但是系統不用承諾我要保留這些空間。系統只會建立紀錄該virtual memory範圍的page table,而這些page table占用的空間會被加入commit charge。
  • 當系統透過MapViewOfFile建立memory mapping,可是背後沒有對應到實際的檔案時,系統會使用paging files作為該塊記憶體的backing store。這種狀況下也會增加commit charge,但並不會計入process page quota。因為這個記憶體用量和process較無關(non-persistent memory-mapped file,通常用於IPC)
  • Copy On Write時,背後要拉一塊新的RAM或paging files去對應Write的內容,因此也必須要取得Commit Charge,這類也不會計入process page file quota。
  • Nonpaged and paged pool and other allocation in system space not backed by explicitly associated files. 系統上會有些可以被分頁的記憶體,也有一些不能被分頁的記憶體區塊,這些都會造成commit charge. 也都不會計入Process page file quota
  • Kernel stacks.
  • Page Table、Page Table的保留空間也會占用Commit Charge。
  • Allocations of physical memory made via the Address Windowing Extension (AWE) APIs

常見的記憶體指標

理解Commit Charge和Page Files後,我們來解釋Windows系統常見的記憶體指標。 我自己在查資料、查書,理解這些指標的過程中,覺得相當混亂,有些指標是其他指標的別名,有些在書上有提到,但網路上查不太到資料,讓人相當困擾。 MSDN的官方文件是我目前覺得最準確的溝通方式,因為其包含了該指標可以在哪個Windows API上取得。而且還附上了工作管理員的對照表。 官方的指標分為兩大類,System層級和Process層級,我想下列幾個指標是一般開發者比較常看到,比較重要的。 文件網址: https://msdn.microsoft.com/en-us/library/windows/desktop/aa965225(v=vs.85).aspx

System Memory Performance Information

  • Committed Bytes
  • Committed Limit

Process Memory Performance Information

  • Page File Bytes
  • Private Bytes
  • Virtual Bytes
  • Working Set
  • Working Set - Private

官方文件網址有列出如何透過Windows API取得上述指標,因此我在這邊著重在各項指標的解釋。

  • Commit Bytes

    • 這是一個系統層級的指標。
    • number of bytes of virtual(not reserved) memory that has been committed. 整個系統中,保證該virtual memory在實體RAM或paging files中會留有一席之地的記憶體數量。
  • Commit Limit

    • 這是一個系統層級的指標
    • 整個系統上可以保證分配給Virtual Memory的空間,包含了RAM和paging files, 當然如果paging files能夠expanding的話,該限制會放寬(是一個soft limit)。
  • Private Bytes, Page File Bytes

    • 這兩個值是一樣的
    • 這是一個Process層級的指標
    • The current size of memory committed to a worker process, which cannot be shared with other processes.
    • 該process已經要求的記憶體量,你可以想像成是Process中Commit Bytes的數量,該指標之所以稱之為Private,是因為排除了像是dll檔案的memory-mapped files所占用的記憶體,注意你無法分辨private bytes的變動來自該process本身,還是所引用的dll執行所造成的。
    • 這個指標並不等於實際的記憶體使用量,commit的記憶體只是系統會留一塊空間,但程式並不保證會使用到。
    • 這個和Physical Memory無關,所以你無法分辨這個數值中,有多少在disk或ram上。
  • Process: Virtual Bytes

    • 這是一個Process層級的指標
    • 該Process所有Virtual Memory Area的範圍總和。
    • The total virtual memory allocation of the process, including mapped regions, private committed regions, and private reserved regions.
  • Working Set

      • 這是一個Process層級的指標
    • 簡單但有一點小瑕疵的解釋是,access不會產生page fault的記憶體量。更簡略的解釋是該Process存在於實體RAM中的記憶體量,而不是該Process所有的記憶體量。所謂的小瑕疵指的是已經備份到page file但還是RAM中的的standby page list並不會計入Working Set。

    • Working Set有計入memory-mapped files,也就是有計入程式間共用的dll。如果把所有Process的Working Set Memory加總會會重複計算到共用的部分。

  • Working Set Private

    • 這是一個Process層級的指標
    • 同Working Set,但只包含該Process自己使用的部分,不包含共用的memory mapping file(如dll)。
    • 關於Working Set和Working Set Private, 這個stackoverflow有個有趣的蠟筆比喻。

雜項

順帶一提,上述那些Memory相關的指標,對於Memory Leak除錯基本上都沒太大幫助。 Working Set顯示的是在實體記憶體中的數量。和程式所消耗的總記憶體相關性有限。Private Bytes稍微有幫助一點,但是你無法分辨該數值的增加是來自程式本身還是他所引用的dll檔。Virtual Bytes是個不能精確反映程式實際分配記憶體量的指標。

工具

Windows Internals提供許多分析Memory的工具,有些蠻好玩的可以裝,玩一玩會覺得Task Manager很弱XD。都是免費的,google查一查直接裝就好。

  • VMMap 看虛擬記憶體
  • RAMMap 看實體記憶體
  • Process Explorer 比Task Manager更詳細的Process資訊
  • Process Monitor

Reference: