在我的高階除錯之旅中,我經常有朋友問我什麼是工作集(記憶體),什麼是提交大小,什麼是虛擬大小,什麼是工作集。 截圖如下:
由於有很多朋友問,這些都不太容易用語言描述,所以我只是早上有時間系統地談談。
正如你們中的一些人可能知道的那樣,記憶體中的虛擬位址分為三類。
reserved(預訂位址) committed (提交位址) free (野生位址) 上面的 reservation + submission 就是我們的虛擬大小,即虛擬大小 = reserved + committed。
當然,言語是沒有根據的,你要拿出證據,寫乙個x86 C測試**,參考以下內容:
static void main(string args)
執行後用windbg附加程式,使用!address -summary 將計算出的記憶體與 Process Explorer 工具顯示的虛擬大小進行比較,如下所示
一些比較嚴肅的朋友可能會說:探險家顯示163300,而 windbg 顯示 163281,為什麼還差了一點,其實這是不同工具的統計誤差,僅此而已。
正如你們中的一些人可能知道的那樣,程式占用的記憶體最終會落在三個地方:
物理記憶體模組虛擬記憶體頁面檔案物理檔案對映檔案這裡的工作集特指物理記憶體模組,因為 Windows 有 mappedfile 檔案對映(記憶體共享)機制,所以物理記憶體模組上的記憶體可以進一步分為自己的獨佔+大家共享,可能有些朋友比較困惑,截圖如下:
在此圖的基礎上,它轉換為技術術語:
Workding Set = WS Private + WS Shareable最後,我們還是用資源管理器來觀察剛才的 C 程式,截圖如下:
正如我們前面提到的,記憶體最終會落在三個地方,其中乙個是虛擬記憶體(pagefile),它用於輔助物理記憶體,即頁面檔案Sys 預設在 C 盤上,截圖如下:
有了這些基礎,是時候想出乙個公式了。
Private Bytes = WS Private + Pages Out (PageFile)上面的 pages out 是我對分頁記憶體的定義,這個 private bytes 指標在記憶體洩漏的情況下特別有用,因為它可以深入了解當前程式是否有大量頁面輸出。
為了說明大量的頁面交換記憶體,請編寫乙個不斷傾注資料的示例。
internal class program "); console.writeline("成功!"); console.readline();
執行程式後,截圖如下:
根據公式:pages out = private bytes - ws private,我們可以看到大約 29GB 必須儲存在 pagefile 中。
本來想用wmic pagefile get value來檢視當前機器的虛擬記憶體占用情況,發現有時候不準確,也沒太深入挖掘,輸出如下:
c:\users\administrator>wmic pagefile get /valueallocatedbasesize=49464caption=c:\pagefile.syscurrentusage=1473description=c:\pagefile.sysinstalldate=20230807095038.481750+480name=c:\pagefile.syspeakusage=1640status=temppagefile=false
但是,正如你所看到的,這個頁面檔案系統已經從開始到48G已經飆公升到49G,其中大部分都被我的程式吞噬了。
這也是很多朋友會問的,WS Shareable 和 WS Shared 有什麼區別,從字面上看:乙個是可以被多個程序共享的記憶體頁集合,乙個是已經共享的記憶體頁的集合。
你可能有點困惑,但沒關係,你可以借助 vmmap 工具觀察它。
啟動 consoleapp6 程序觀察
從圖中可以看出,shareable=104k 和 shared=0k,這意味著什麼?感謝 consoleapp6exe 是乙個對映到記憶體的檔案,占用了 104k 的物理記憶體,沒有其他程序共享這塊物理記憶體,所以此時是 shared=0,這裡填寫 shared 最簡單的方法是開啟多個 consoleapp6 例項。
開啟多個 consoleapp6 程序觀察,然後反覆點選 consoleapp6 生成多個例項,再次使用 vmmap 觀察,截圖如下:
我盡力使用多種觀察工具眼見為實希望你不要再對這些術語感到困惑,如果以後有人問類似的問題,你可以把這個問題扔過去,減輕你我的負擔。