1. 程式人生 > >windows平臺一個程式究竟佔用多少記憶體?

windows平臺一個程式究竟佔用多少記憶體?

http://blog.csdn.net/jaminwm/article/details/1394993

首先宣告:

        Virtual memory 和 memory swapping的概念對於UNIX等系統是兩個界限很明顯的概念,但是對於windows系統來說區別這兩個概念無疑是沒有意義的,在windows封裝得複雜而又機密的虛擬記憶體管理技術下研究與區別他們沒有什麼實際意義。

注意:以上宣告很重要,否則你幾乎可以把下面我的程式與分析全盤否決,呵呵

        最近工作需要研究linux系統程式設計,需要了解LINUX虛擬記憶體管理技術,看到一本譯本好書深入理解LINUX虛擬記憶體管理

》原書名:《understanding the linux virtual memory manger》作者愛爾蘭人Mel Gorman ,翻譯:華中科技大學 白洛等人。北京航空航天大學出版社出版,該書推薦給大家,一定不負您的76塊大洋 ,呵呵。

        標題是記憶體的東東,我們先了解一下實體記憶體和虛擬記憶體。實體記憶體,在應用中,自然是顧名思義,物理上,真實的插在板子上的記憶體是多大就是多大了.看機器配置的時候,看的就是這個實體記憶體。如果執行的程式很大或很多,就會導致實體記憶體消耗殆盡.為了解決這個問題,Windows中運用了虛擬記憶體技術,即拿出一部分硬碟空間來充當記憶體使用,當記憶體佔用完時,電腦就會自動呼叫硬碟來充當記憶體,以緩解記憶體的緊張。

        一個程式,不可避免地要用到虛擬記憶體,因為不頻繁執行或者已經很久沒有執行的程式碼,沒有必要留在實體記憶體中,只會造成浪費;放在虛擬記憶體中,等執行這部分程式碼的時候,再調出來。Windows 的工作管理員可以幫助我們看到程序的虛擬記憶體.調出工作管理員,點選選單“檢視”-“選擇列”,在出現的視窗中,鉤上“虛擬記憶體大小”,如下

點“確定”,這個時候,程序列表中已經顯示各程序的虛擬記憶體大小,如下

        一個程式到底應該使用多少虛擬記憶體呢?不一定,但是應該以恰到好處的符合虛擬記憶體原本作用為最好,下面將探討表面看起來呼叫了大量圖片、大量執行庫的程式,為什麼才“佔用”不到 1 MB 的記憶體的原因。

        通過BCB6的WinSight32,以及SPY++檢視原來是 SetProcessWorkingSetSize 函式的呼叫造成的。(這話不嚴謹,也不知道怎麼表達更好,講究著看吧)

       MSDN 對該函式的表述(翻譯):使用這個函式來設定應用程式最小和最大的執行空間,只會保留需要的記憶體.當應用程式被閒置或系統記憶體太低時,作業系統會自動呼叫這個機制來設定應用程式的記憶體.應用程式也可以使用 VirtualLock 來鎖住一定範圍的記憶體不被系統釋放;當你加大執行空間給應用程式,你能夠得到的實體記憶體取決於系統,這會造成其他應用程式降低效能或系統總體降低效能,這也可能導致請求實體記憶體的操作失敗,例如:建立 程序,執行緒,核心池,就必須小心的使用該函式.

      也就是說,該函式不是節省記憶體,而是強制把程序的實體記憶體搬到虛擬記憶體中.

       另外有一些資料上說,該函式“將有可能導致缺頁中斷,嚴重影響效能”.
函式原型:
BOOL SetProcessWorkingSetSize(
HANDLE hProcess,
SIZE_T dwMinimumWorkingSetSize,
SIZE_T dwMaximumWorkingSetSize
);
我們用 VB 來做這麼一個簡單的例子,是程式佔用 300 KB 記憶體吧.

建立一個標準的 VB 工程,在 Form1 中放置一個 Timer1 ,把 Interval 屬性設定為 1000 (即 1 秒).然後在程式碼編輯框中輸入以下程式碼:

Private Declare Function SetProcessWorkingSetSize Lib "kernel32" (ByVal hProcess As Long, ByVal dwMinimumWorkingSetSize As Long, ByVal dwMaximumWorkingSetSize As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Sub Timer1_Timer()
SetProcessWorkingSetSize GetCurrentProcess(), 50000, 100000
End Sub
然後生成 工程1.exe,執行,調出工作管理員檢視,發現記憶體佔用才 320 KB.如果把定時器關閉,這程序的記憶體一般 4 MB左右.
必須定時執行該函式,否則虛擬記憶體會慢慢被調出來,恢復原來的記憶體大小.
如果要使一個本來需要佔用大量記憶體的程式減低到幾百 KB ,使用同樣的方法即可.

如果 SetProcessWorkingSetSize 函式被正常使用,是非常有用處的.但是為了矇騙使用者的眼睛,每秒,甚至幾十毫秒就把大量記憶體往虛擬記憶體裡面壓,就會帶來無可預計的危害.看看這篇文章怎麼說:“因為他只是暫時的將應用程式佔用的記憶體移至虛擬記憶體,一旦,應用程式被啟用或者有操作請求時,這些記憶體又會被重新佔用.如果你強制使用該方法來設定程式佔用的記憶體,那麼可能在一定程度上反而會降低系統性能,因為系統需要頻繁的進行記憶體和硬碟間的頁面交換.”.

沒錯,如果你使用了這類軟體,意味著你的硬碟將每秒將 I/O 大量資料;硬碟的磁針將拼命旋轉...(當然硬碟磁針不可能不旋轉^_^,只是選擇得更厲害而已).

不是說 BT 很傷記憶體嗎?不然,因為現在大多 BT 軟體都有快取技術.且看 Bitcomet 官方對快取技術的說明:“傳統BT高速下載時硬碟會響得很厲害,這是大量的隨機讀取造成的.... BitComet可以由使用者設定快取大小.... 可以明顯地看出犧牲一小部分記憶體作快取對硬碟的保護作用.”

是不是有種心寒的感覺?一類軟體寧願犧牲記憶體,也要減少保護硬碟;而另外一類軟體,卻為了欺騙使用者,讓CPU、硬碟更加奔波......這類軟體不少,我以其中一個桌面工具為例,揭穿它的假面具(不點名字了).執行該軟體後,隨意操作一下,然後開啟程序管理器,把虛擬記憶體列調出來。OK,20 MB 虛擬記憶體,而只有 632 KB 實體記憶體.細心的你會發現,大概每 1 秒,該行都有閃爍的感覺,沒錯,這正是每秒呼叫 SetProcessWorkingSetSize 的結果.另外,我們開啟 Norton Process Viewer ,檢視該程序的 CPU 佔用情況,可以看到,就算沒有操作該軟體,但是每秒,都有 3% 的CPU佔用起伏(雖然這並不能說明什麼).另外,記憶體框中可以看到實體記憶體和虛擬記憶體的佔用,兩者相去甚遠.此外,可以用 Hook API 技術來證明每秒呼叫 SetProcessWorkingSetSize 的行為.

我們應該怎麼做

這篇文章只想讓使用者瞭解軟體佔用資源的實際.而程式設計師應該把下功夫,真正從程式碼中減少記憶體的消耗,而不是一味忽悠使用者.呼叫 SetProcessWorkingSetSize 會帶來某些好處,但是何時呼叫、如何呼叫應該符合兩個要求:
1,在程式暫時不被使用的時候(例如最小化);
2,實體記憶體和虛擬記憶體應處於一個合適的比例(而不是 600 KB 比 20 MB 這麼荒唐);
3,或者不呼叫,讓 Windows 去處理.

有空再仔細瞭解WINDOWS的記憶體操作技術吧,不寫了,繼續看書,