C# Winform应用程序占用内存较大解决方法整理(转)-- SetProcessWorkingSetSize
一、C# Winform應(yīng)用程序占用內(nèi)存較大解決方法整理(轉(zhuǎn))
原文:? http://www.jb51.net/article/56682.htm
背景:
微軟的 .NET FRAMEWORK 現(xiàn)在可謂如火如荼了。但是,.NET 一直所為人詬病的就是“胃口太大”,狂吃內(nèi)存,雖然微軟聲稱 GC 的功能和智能化都很高,但是內(nèi)存的回收問題,一直存在困擾,尤其是 winform 程序,其主要原因是因為.NET程序在啟動時,是需要由JIT動態(tài)編譯并加載的,這個加載會把所有需要的資源都加載進(jìn)來,很多資源是只有啟動時才用的。
以XP 系統(tǒng)為例子,程序啟動后,打開任務(wù)管理器,會看到占用的內(nèi)存量比較大,你把程序最小化,會發(fā)現(xiàn)該程序占用的內(nèi)存迅速減小到一個很小的值,再恢復(fù)你的程序,你會發(fā)現(xiàn)內(nèi)存占用又上升了,但是比你剛啟動時的內(nèi)存占用值還是小的,這就是一個資源優(yōu)化的過程,這個過程是操作系統(tǒng)主動完成的。
結(jié)論與展望:
創(chuàng)新設(shè)計大賽的項目已經(jīng)快到交付的日期了,都說Winform占用內(nèi)存大,于是想著看看自己寫的基于手機郵件的遠(yuǎn)程關(guān)機軟件(Mail_Based_Remote_Shutdown)占用內(nèi)存情況,整個開發(fā)過程自己也在盡量寫一些比較優(yōu)美的代碼來減少系統(tǒng)內(nèi)存占用,今天看了下,剛打開時占用20M內(nèi)存,然后一點點增加,最后到80多M,真是無法忍受,每次都是寫了之后回過頭來才發(fā)現(xiàn)自己的代碼很丑,系統(tǒng)架構(gòu)師的作用就體現(xiàn)出來了。
這里整理了一些網(wǎng)上關(guān)于Winform如何降低系統(tǒng)內(nèi)存占用的資料,供參考:
1、使用性能測試工具dotTrace 3.0,它能夠計算出你程序中那些代碼占用內(nèi)存較多
 2、強制垃圾回收
 3、多dispose,close
 4、用timer,每幾秒鐘調(diào)用:SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);具體見附錄。
 5、發(fā)布的時候選擇Release
 6、注意代碼編寫時少產(chǎn)生垃圾,比如String + String就會產(chǎn)生大量的垃圾,可以用StringBuffer.Append
 7、this.Dispose();??? this.Dispose(True);?? this.Close();??? GC.Collect();?? 
 8、注意變量的作用域,具體說某個變量如果只是臨時使用就不要定義成成員變量。GC是根據(jù)關(guān)系網(wǎng)去回收資源的。
 9、檢測是否存在內(nèi)存泄漏的情況,詳情可參見:內(nèi)存泄漏百度百科
附錄:定期清理執(zhí)行垃圾回收代碼:
#region 內(nèi)存回收[DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")]public static extern int SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);/// <summary>/// 釋放內(nèi)存/// </summary>public static void ClearMemory(){GC.Collect();GC.WaitForPendingFinalizers();if (Environment.OSVersion.Platform == PlatformID.Win32NT){App.SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);}}#endregion二、SetProcessWorkingSetSize函數(shù)的騙局
原文地址:http://blog.sina.com.cn/s/blog_49f8960e0100081x.html
我實在不愿意提起這個話題.后來在網(wǎng)上看到幾篇文章,深深感覺到,已經(jīng)有程序員站出來,揭穿這個忽悠了千百萬用戶的詭計了...
 附2篇文章的地址:
 http://blog.csdn.net/biku/archive/2006/07/06/886038.aspx
 http://blog.csdn.net/zlt982001/archive/2005/08/28/466879.aspx
 我這篇文章無非是歸納了幾篇文章的內(nèi)容,并深入的闡明惡意使用該技術(shù)帶來的壞處.
 請一味追求低內(nèi)存軟件的用戶們注意了:什么才應(yīng)該是選擇軟件的主要因素.
物理內(nèi)存和虛擬內(nèi)存
物理內(nèi)存,在應(yīng)用中,自然是顧名思義,物理上,真實的插在板子上的內(nèi)存是多大就是多大了.看機器配置的時候,看的就是這個物理內(nèi)存.
如果執(zhí)行的程序很大或很多,就會導(dǎo)致物理內(nèi)存消耗殆盡.為了解決這個問題,Windows中運用了虛擬內(nèi)存技術(shù),即拿出一部分硬盤空間來充當(dāng)內(nèi)存使用,當(dāng)內(nèi)存占用完時,電腦就會自動調(diào)用硬盤來充當(dāng)內(nèi)存,以緩解內(nèi)存的緊張.
一個程序,不可避免地要用到虛擬內(nèi)存,因為不頻繁執(zhí)行或者已經(jīng)很久沒有執(zhí)行的代碼,沒有必要留在物理內(nèi)存中,只會造成浪費;放在虛擬內(nèi)存中,等執(zhí)行這部分代碼的時候,再調(diào)出來.
 Windows 的任務(wù)管理器可以幫助我們看到進(jìn)程的虛擬內(nèi)存.調(diào)出任務(wù)管理器,點擊菜單“查看”-“選擇列”,在出現(xiàn)的窗口中,鉤上“虛擬內(nèi)存大小
一個程序到底應(yīng)該使用多少虛擬內(nèi)存呢?不一定,但是應(yīng)該以恰到好處的符合虛擬內(nèi)存原本作用為最好.
 下面將揭穿表面看起來調(diào)用了大量圖片、大量運行庫的程序,為什么才“占用”不到 1 MB 的內(nèi)存的詭計.
原來是 SetProcessWorkingSetSize 函數(shù)
MSDN 對該函數(shù)的表述(翻譯):使用這個函數(shù)來設(shè)置應(yīng)用程序最小和最大的運行空間,只會保留需要的內(nèi)存.當(dāng)應(yīng)用程序被閑置或系統(tǒng)內(nèi)存太低時,操作系統(tǒng)會自動調(diào)用這個機制來設(shè)置應(yīng)用程序的內(nèi)存.應(yīng)用程序也可以使用 VirtualLock 來鎖住一定范圍的內(nèi)存不被系統(tǒng)釋放;當(dāng)你加大運行空間給應(yīng)用程序,你能夠得到的物理內(nèi)存取決于系統(tǒng),這會造成其他應(yīng)用程序降低性能或系統(tǒng)總體降低性能,這也可能導(dǎo)致請求物理內(nèi)存的操作失敗,例如:建立 進(jìn)程,線程,內(nèi)核池,就必須小心的使用該函數(shù).
也就是說,該函數(shù)不是節(jié)省內(nèi)存,而是強制把進(jìn)程的物理內(nèi)存搬到虛擬內(nèi)存中.
另外有一些資料上說,該函數(shù)“將有可能導(dǎo)致缺頁中斷,嚴(yán)重影響性能”.
 函數(shù)原型:
 BOOL SetProcessWorkingSetSize(
 HANDLE hProcess,
 SIZE_T dwMinimumWorkingSetSize,
 SIZE_T dwMaximumWorkingSetSize
 );
 我們用 VB 來做這么一個簡單的例子,是程序占用 300 KB 內(nèi)存吧.
建立一個標(biāo)準(zhǔn)的 VB 工程,在 Form1 中放置一個 Timer1 ,把 Interval 屬性設(shè)置為 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,執(zhí)行,調(diào)出任務(wù)管理器查看,發(fā)現(xiàn)內(nèi)存占用才 320 KB.如果把定時器關(guān)閉,這進(jìn)程的內(nèi)存一般 4 MB左右.
 必須定時執(zhí)行該函數(shù),否則虛擬內(nèi)存會慢慢被調(diào)出來,恢復(fù)原來的內(nèi)存大小.
 如果要使一個本來需要占用大量內(nèi)存的程序減低到幾百 KB ,使用同樣的方法即可.
詭計帶來的危害
如果 SetProcessWorkingSetSize 函數(shù)被正常使用,是非常有用處的.但是為了蒙騙用戶的眼睛,每秒,甚至幾十毫秒就把大量內(nèi)存往虛擬內(nèi)存里面壓,就會帶來無可預(yù)計的危害.看看這篇文章怎么說:“因為他只是暫時的將應(yīng)用程序占用的內(nèi)存移至虛擬內(nèi)存,一旦,應(yīng)用程序被激活或者有操作請求時,這些內(nèi)存又會被重新占用.如果你強制使用該方法來設(shè)置程序占用的內(nèi)存,那么可能在一定程度上反而會降低系統(tǒng)性能,因為系統(tǒng)需要頻繁的進(jìn)行內(nèi)存和硬盤間的頁面交換.”.
沒錯,如果你使用了這類軟件,意味著你的硬盤將每秒將 I/O 大量數(shù)據(jù);硬盤的磁針將拼命旋轉(zhuǎn)...(當(dāng)然硬盤磁針不可能不旋轉(zhuǎn)^_^,只是選擇得更厲害而已).
不是說 BT 很傷內(nèi)存嗎?不然,因為現(xiàn)在大多 BT 軟件都有緩存技術(shù).且看 Bitcomet 官方對緩存技術(shù)的說明:“傳統(tǒng)BT高速下載時硬盤會響得很厲害,這是大量的隨機讀取造成的.... BitComet可以由用戶設(shè)置緩存大小.... 可以明顯地看出犧牲一小部分內(nèi)存作緩存對硬盤的保護作用.”
是不是有種心寒的感覺?一類軟件寧愿犧牲內(nèi)存,也要減少保護硬盤;而另外一類軟件,卻為了欺騙用戶,讓CPU、硬盤更加奔波......
抓一個兇手
這類軟件不少,我以其中一個桌面工具為例,揭穿它的假面具(不點名字了).運行該軟件后,隨意操作一下,然后打開進(jìn)程管理器,把虛擬內(nèi)存列調(diào)出來,找到該進(jìn)程,如圖3:
OK,20 MB 虛擬內(nèi)存,而只有 632 KB 物理內(nèi)存.細(xì)心的你會發(fā)現(xiàn),大概每 1 秒,該行都有閃爍的感覺,沒錯,這正是每秒調(diào)用 SetProcessWorkingSetSize 的結(jié)果.另外,我們打開 Norton Process Viewer ,查看該進(jìn)程的 CPU 占用情況,如圖4:
可以看到,就算沒有操作該軟件,但是每秒,都有 3% 的CPU占用起伏(雖然這并不能說明什么).另外,內(nèi)存框中可以看到物理內(nèi)存和虛擬內(nèi)存的占用,兩者相去甚遠(yuǎn).此外,可以用 Hook API 技術(shù)來證明每秒調(diào)用 SetProcessWorkingSetSize 的行為.
應(yīng)該怎么做
這篇文章只想讓用戶了解軟件占用資源的實際.而程序員應(yīng)該把下功夫,真正從代碼中減少內(nèi)存的消耗,而不是一味忽悠用戶.調(diào)用 SetProcessWorkingSetSize 會帶來某些好處,但是何時調(diào)用、如何調(diào)用應(yīng)該符合兩個要求:
 1,在程序暫時不被使用的時候(例如最小化);
 2,物理內(nèi)存和虛擬內(nèi)存應(yīng)處于一個合適的比例(而不是 600 KB 比 20 MB 這么荒唐);
 3,或者不調(diào)用,讓 Windows 去處理.
三、揭發(fā)天氣秀、桌面秀、雪狐等號稱資源占用小的桌面軟件的流氓行為!
原文:http://blog.csdn.net/biku/article/details/886038以下內(nèi)容需要你對虛擬內(nèi)存和內(nèi)存有所了解,但目的只是告訴大家,這些所謂對內(nèi)存占用小的軟件是最為傷硬盤的!
 
 很多人都用過天氣秀、雪狐、曰歷秀、桌面秀等等桌面軟件。這類軟件有個最大的特點就是在任務(wù)管理器里看,內(nèi)存占用N小,比記事本都小,只有幾百K。很多人就是沖著這點才用這些軟件的。
 
 但是,也許大家不知道,這些軟件才是占用資源的大戶。
 這些軟件占用資源為什么這么少呢?
 Windows編程里有個方法叫做SetProcessWorkingSetSize,對編程有所了解的可以搜索一下。這個方法能夠設(shè)定程序所占用的內(nèi)存數(shù)(當(dāng)然有一個最小值)。
 
 比如你打開一個程序,把它最小化,再看任務(wù)管理器,里面占用的內(nèi)存數(shù)就是它所使用的最小值,其他暫時用不到的代碼就被放到了虛擬內(nèi)存里。但是,這樣做,是影響性能Windows把最多的內(nèi)存分配給了前臺正在運行的程序。
 
 而天氣秀等軟件所號稱的內(nèi)存壓縮技術(shù),就是調(diào)用這個SetProcessWorkingSetSize,把內(nèi)存中的程序代碼放到虛擬內(nèi)存里,調(diào)用一次還不夠,因為程序運行內(nèi)存占用不停變化。所以要設(shè)定一個Timer(計時器),每隔一段時間就調(diào)用一次(通常是幾毫秒)。
 
 
 虛擬內(nèi)存是指硬盤上的一部分空間。也就是說,當(dāng)這些軟件運行時,每隔幾毫秒,你的電腦CPU就要強制把內(nèi)存中的代碼放到硬盤上--往硬盤不停地寫。
 說實話,這種方式來實現(xiàn)內(nèi)存占用少(實際上并沒有少)很BT。
 
 
 上面所提到的方法SetProcessWorkingSetSize,是微軟提供給程序員的一個方法(或稱函數(shù))。
 所以在這里,提醒大家:千萬不要相信宣傳!這些所謂對內(nèi)存占用小的軟件是最占資源最為傷硬盤的!?
 
 
 
 
總結(jié)
以上是生活随笔為你收集整理的C# Winform应用程序占用内存较大解决方法整理(转)-- SetProcessWorkingSetSize的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: java局域网聊天代码_简单的局域网聊天
 - 下一篇: 《读不透劳动合同法,决不能做HR(新劳动