Windows任務管理器默認情況下,“內存(私人工作集)”列處於選中狀態。
內存 - 工作集:是私人工作集中的內存數量與進程正在使用且可以由其他進程共享的內存數量的總和。
內存 - 峰值工作集:是進程所使用的工作集內存的最大數量。
內存 - 工作集增量:是進程所使用的工作集內存中的更改量。
內存 - 專用工作集:- 是工作集的一個子集,它是描述每個進程所使用的內存數量的技術術語。專用工作集專門描述了某個進程正在使用的且無法與其他進程共享的內存數量。
內存 - 提交大小:是為某進程使用而保留的虛擬內存的數量。
內存 - 頁面緩沖池:是可以寫入其他存儲媒體(例如硬盤)的某個進程的認可虛擬內存數量。
內存 - 非頁面緩沖池:是無法寫入其他存儲媒體的某個進程的認可虛擬內存數量。
一. SetProcessWorkingSetSize 的工作原理
看看這個API SetProcessWorkingSetSize
這是從MSDN摘下的原話
Using the SetProcessWorkingSetSize function to set an application's minimum and maximum working set sizes does not guarantee that the requested memory will be reserved, or that it will remain resident at all times. When the application is idle, or a low-memory situation causes a demand for memory, the operating system can reduce the application's working set. An application can use the VirtualLock function to lock ranges of the application's virtual address space in memory; however, that can potentially degrade the performance of the system.
使用這個函數來設置應用程序最小和最大的運行空間,只會保留需要的內存。當應用程序被閑置或系統內存太低時,操作系統會自動調用這個機制來設置應用程序的內存。應用程序也可以使用 VirtualLock 來鎖住一定范圍的內存不被系統釋放。
When you increase the working set size of an application, you are taking away physical memory from the rest of the system. This can degrade the performance of other applications and the system as a whole. It can also lead to failures of operations that require physical memory to be present; for example, creating processes, threads, and kernel pool. Thus, you must use the SetProcessWorkingSetSize function carefully. You must always consider the performance of the whole system when you are designing an application.
當你加大運行空間給應用程序,你能夠得到的物理內存取決於系統,這會造成其他應用程序降低性能或系統總體降低性能,這也可能導致請求物理內存的操作失敗,例如:建立 進程,線程,內核池,就必須小心的使用該函數。
========================
事實上,使用該函數並不能提高什么性能,也不會真的節省內存。
因為他只是暫時的將應用程序占用的內存移至虛擬內存,一旦,應用程序被激活或者有操作請求時,這些內存又會被重新占用。如果你強制使用該方法來 設置程序占用的內存,那么可能在一定程度上反而會降低系統性能,因為系統需要頻繁的進行內存和硬盤間的頁面交換。
BOOL SetProcessWorkingSetSize(
HANDLE hProcess,
SIZE_T dwMinimumWorkingSetSize,
SIZE_T dwMaximumWorkingSetSize
);
將 2個 SIZE_T 參數設置為 -1 ,即可以使進程使用的內存交換到虛擬內存,只保留一小部分代碼
1 。當我們的應用程序剛剛加載完成時,可以使用該操作一次,來將加載過程不需要的代碼放到虛擬內存,這樣,程序加載完畢后,保持較大的可用內存。
2.程序運行到一定時間后或程序將要被閑置時,可以使用該命令來交換占用的內存到虛擬內存。
二. 區分物理內存、虛擬內存、Working Set(Memory)、Memory
以下來自:http://blog.joycode.com/qqchen/archive/2004/03/17/16434.aspx
這個問題在CSDN上碰到好幾次,我每次都只給出了簡單的答案:不要參考Task Manager的Mem Usage數據,那個數據的大小對程序性能沒有直接影響。
下面是我分析這問題的一些思路,希望對對這個問題感興趣的朋友有所幫助
Q: Is .NET Alone?
A: Nope! 前面Saucer說過了,這不是.NET的問題,所有Windows程序都有類似的行為。例如下面的C程序:
void main { while(1); } //死循環,便於我們察看Task Manager
初次運行在我的機器上Mem Usage是632K,把Console最小化以后再恢復,Mem Usage變成了36K。顯然,這不是一個.NET獨有的問題,而是Windows Memory Management的問題。那么和.NET的GC機制也不會有太大的關系——雖然問題的表現形式很容易讓人聯想到GC。
Q: How much memory does my program use?
A: 回答這個問題並不容易。先來看看操作系統虛擬內存管理的一些基本概念:每個Windows進程都擁有4G的地址空間,但是你的機器顯然沒有4G的物理內存。在多任務環境下,所有進程使用的內存總和可以超過計算機的物理內存。在特定的情況下,進程的一部分可能會從物理內存中刪除而被暫存在硬盤的文件里(pagefile),當進程試圖訪問這些被交換到pagefile里的內存的時候,系統會產生一個缺頁中斷(page fault),這時候Windows內存管理器會負責把對應的內存頁重新從硬盤調入物理內存。
在某個時間內,一個進程可以直接訪問到的物理內存(不發生缺頁中斷)叫做這個進程的Working Set;而一個進程從4G的地址空間當中實際分配(commit)了的、可訪問的內存稱為Committed Virtual Memory。Committed VM可能存在於Page File當中,WorkingSet則一定位於物理內存。
所以要回答上面的問題先要反問一句:What're you talking about? Physical Memory or Committed Memory?
Q: What is this "Mem Usage" data?
A: From Task Manager Help: In Task Manager, the current Working Set of a process, in kilobytes.
Mem Usage這個名字多少有些誤導。它只表示這個進程當前占用的物理內存,也就是WorkingSet。WorkingSet不表示進程當前“占用”的所有虛擬內存,該進程可能還有一部分數據被交換到pagefile當中。這些數據只有在被訪問的時候才會被加載到物理內存。
Task Manager有另一列數據:VM Size,表示了一個進程分配的虛存(Committed Visual Memory)——實際的定義要比這個復雜一些,但這個定義對我們目前分析的問題已經足夠了。以前面的C程序為例,在最小化前后的VM Size都是176K,並沒有變化。
所以,結論很簡單:當一個Windows程序被最小化的時候,Windows內存管理器把該進程的WorkingSet減到最小(根據先進先出FIFO或者最近最少使用LRU),把大部分數據交換到pagefile里。這很容易理解:我們通常總是希望為前台的應用程序留出更多物理內存,從而具有更好的性能。當該程序從最小化恢復的時候,Windows也不會完全加載程序的所有虛存,只是加載了必要的部分。這也很容易理解:程序啟動階段的代碼通常在啟動之后很少訪問(對.NET程序尤其如此,向fusion這樣的模塊在程序正常加載之后如果沒有用到Reflection通常用不到)。
Q: So, Do we want a smaller workingset, or a larger one?
A: It depends. Conventional Wisdom tells us: The smaller, the better. 但是在虛存的問題上卻沒這么簡單。如果WorkingSet太小,程序運行過程中會產生很多缺頁中斷,這會嚴重影響程序的性能。另一方面,WorkingSet太大會浪費“寶貴的”物理內存,降低整個系統的性能。 通常情況下(除非是對性能非常敏感的應用程序,並且你對Windows的內存管理了如指掌),建議不要在程序中自己調整WorkingSet的大小,而把這個任務交給Windows內存管理器。調整的方法Saucer有提到: SetProcessWorkingSetSize();
Q: Final Question, Does my program really occupy that much physical memory?
A: 這個問題看上去土了點——那個數字明明白白的寫在Task Manager里面。
sam1111用vadump檢查的結果顯示進程WorkingSet減小的主要原因是很多DLL在從最小化恢復的時候沒有被加載到物理內存。我們知道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數據,那個數據的大小對程序性能沒有直接影響。用Perfomence Monitor里面與.NET相關的Counter要容易、准確的多
————————————————
版權聲明:本文為CSDN博主「jiangqin115」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/jiangqin115/article/details/47108783