在多任務環境下,所有進程使用的內存總和可以超過計算機的物理內存。
在特定的情況下,進程的壹部分可能會從物理內存中刪除而被暫存在硬盤的文件裏(pagefile),當進程試圖訪問這些被交換到pagefile裏的內存的時候,系統會產生壹個缺頁中斷(page
fault),這時候Windows內存管理器會負責把對應的內存頁重新從硬盤調入物理內存。
註意:
1)在某個時間內,壹個進程可以直接訪問到的物理內存(不發生缺頁中斷)叫做這個進程的Working
Set;
2)而壹個進程從4G的地址空間當中實際分配(commit)了的、可訪問的內存稱為Committed
Virtual
Memory。
3)Committed
VM可能存在於Page
File當中,WorkingSet則壹定位於物理內存。
Mem
Usage這個名字多少有些誤導。它只表示這個進程當前占用的物理內存,也就是WorkingSet。WorkingSet不表示進程當前?占用?的所有虛擬內存,該進程可能還有壹部分數據被交換到pagefile當中。這些數據只有在被訪問的時候才會被加載到物理內存。
Task
Manager有另壹列數據:VM
Size,表示了壹個進程分配的虛存(Committed
Visual
Memory)?實際的定義要比這個復雜壹些,但我們可以暫時看成?壹個進程分配的虛存?。
當壹個Windows程序被最小化的時候,Windows內存管理器把該進程的WorkingSet減到最小(根據先進先出FIFO或者最近最少使用LRU),把大部分數據交換到pagefile裏。
這很容易理解:我們通常總是希望為前臺的應用程序留出更多物理內存,從而具有更好的性能。當該程序從最小化恢復的時候,Windows也不會完全加載程序的所有虛存,只是加載了必要的部分。這也很容易理解:程序啟動階段的代碼通常在啟動之後很少訪問(對.NET程序尤其如此,向fusion這樣的模塊在程序正常加載之後如果沒有用到Reflection通常用不到)。
但是在虛存的問題上卻沒這麽簡單。如果WorkingSet太小,程序運行過程中會產生很多缺頁中斷,這會嚴重影響程序的性能。另壹方面,WorkingSet太大會浪費?寶貴的?物理內存,降低整個系統的性能。
通常情況下(除非是對性能非常敏感的應用程序,並且妳對Windows的內存管理了如指掌),建議不要在程序中自己調整WorkingSet的大小,而把這個任務交給Windows內存管理器
我們知道DLL的壹個特點是代碼***享,以NTDLL.DLL為例,整個Windows系統的幾乎所有應用程序(具體地說,Win32子系統的所有程序)都需要引用NTDLL.DLL,如果每人壹份,光這個文件就的占用幾十兆內存。
Windows地解決辦法是只在物理內存中保存壹份NTDLL.DLL的COPY,所有引用這個DLL的程序都把這壹份COPY映射到自己的內存空間裏面,***享NTDLL.DLL的代碼段(每個進程的數據段仍然是獨立的)。
所以雖然NTDLL.DLL的大小被計算在妳的程序的WorkingSet裏面,但是從妳的程序中去掉對這個DLL的引用並不會真的釋放多少物理內存?妳不用,別人還在用呢!
所以,妳的程序?獨占?的物理內存遠沒有Mem
Usage所表示的那麽多,需要從Mem
Usage裏面扣除很多Shared
Code
Page
(vadump裏面可以看到)。
重要結論:
不要參考Task
Manager的Mem
Usage數據,那個數據的大小對程序性能沒有直接影響。