降低Winform佔用系統內存的方法-將物理內存的佔用挪到虛擬內存裏

       最近做導師的項目是通過Socket通信控制一個庫室中所有板子的項目,通過C# WinForm實現的一個PC客戶端,但是.NET 的問題一直就是狂喫內存,雖然說內部提供了GC 的功能和智能化,但是內存的回收問題,一直存在困擾,特別是本項目使用的 Winform 程序,由於.NET程序在啓動時,是需要由JIT動態編譯並加載的,這個加載會把所有需要的資源都加載進來,很多資源是隻有啓動時才用的。同時由於通過socket控制的板子比較多,運行一天後程序佔的內存很多,今天試過多種方法,網上大拿們提供降低Winform佔用系統內存的方法有大概下面幾種:

  • 使用性能測試工具dotTrace 3.0,它能夠計算出你程序中那些代碼佔用內存較多
  • 強制垃圾回收
  • 多dispose,close
  • 用timer,每幾秒鐘調用:SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1)
  • 發佈的時候選擇Release
  • 注意代碼編寫時少產生垃圾,比如String + String就會產生大量的垃圾,可以用StringBuffer.Append
  • this.Dispose();    this.Dispose(True);   this.Close();    GC.Collect();   
  • 注意變量的作用域,具體說某個變量如果只是臨時使用就不要定義成成員變量。GC是根據關係網去回收資源的
  • 檢測是否存在內存泄漏的情況
今天在項目中使用了SetProcessWorkingSetSize的方法,效果很好,查資料顯示這個方法的思想是
轉自 http://blog.csdn.net/zlt982001/article/details/466879

你可以,試試看把一個程序最小化到任務欄,再看看任務管理器,看到沒,你的程序佔用的實際內存一下子減少了,看來並不是我有什麼方法能夠壓縮內存,而是操作系統本身就有這個機制,即當程序不使用時(最小化),操作系統會調用某些命令,來將該程序佔用的內存移至虛擬內存,只保留一小部分常規代碼

所以我們就看到了 這種情景,佔用的內存一下子就縮小了。

那麼:系統到底調用了什麼指令呢?能不能在不縮小窗體的情況下來釋放內存呢?

看看這個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
 dwMaximumWo

將 2個  SIZE_T  參數設置爲 -1 ,即可以使進程使用的內存交換到虛擬內存,只保留一小部分代碼

而桌面日曆秀 之所以能夠 總是保持 最小內存,是因爲使用了定時器,不停的進行該操作,,所以性能可想而知,雖然換來了小內存的假象,對系統來說確實災難。

當然,該函數也並非無一是處,

1 。當我們的應用程序剛剛加載完成時,可以使用該操作一次,來將加載過程不需要的代碼放到虛擬內存,這樣,程序加載完畢後,保持較大的可用內存。

2.程序運行到一定時間後或程序將要被閒置時,可以使用該命令來交換佔用的內存到虛擬內存

下面附上我採用該方法的源代碼(C#)
//需要引用的命名空間
using System.Diagnostics;
using System.Runtime.InteropServices;
 #region 內存回收
        [DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")]
        public static extern int SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);
        /// <summary>
        /// 釋放內存
        /// </summary>
        public static void ClearMemory()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
            }
        }
        /// <summary>
        /// 獲取應用內存
        /// </summary>
        /// <returns></returns>
        public static float getMem()
        {
            string procName = Process.GetCurrentProcess().ProcessName;
            using (PerformanceCounter pc = new PerformanceCounter("Process", "Working Set - Private", procName))
            {
                float r = (pc.NextValue() / 1024 / 1024);
                return r;
            }
        }
        #endregion
上面是主要用到的兩個函數,加上去後程序,效果非常好:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章