1. 程式人生 > >降低Winform佔用系統記憶體的方法-將實體記憶體的佔用挪到虛擬記憶體裡

降低Winform佔用系統記憶體的方法-將實體記憶體的佔用挪到虛擬記憶體裡

你可以,試試看把一個程式最小化到工作列,再看看工作管理員,看到沒,你的程式佔用的實際記憶體一下子減少了,看來並不是我有什麼方法能夠壓縮記憶體,而是作業系統本身就有這個機制,即當程式不使用時(最小化),作業系統會呼叫某些命令,來將該程式佔用的記憶體移至虛擬記憶體,只保留一小部分常規程式碼

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

那麼:系統到底呼叫了什麼指令呢?能不能在不縮小窗體的情況下來釋放記憶體呢?

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

當你加大執行空間給應用程式,你能夠得到的實體記憶體取決於系統,這會造成其他應用程式降低效能或系統總體降低效能,這也可能導致請求實體記憶體的操作失敗,例如:建立 程序,執行緒,核心池,就必須小心的使用該函式。

========================

事實上,使用該函式並不能提高什麼效能,也不會真的節省記憶體。

因為他只是暫時的將應用程式佔用的記憶體移至虛擬記憶體,一旦,應用程式被啟用或者有操作請求時,這些記憶體又會被重新佔用。如果你強制使用該方法來 設定程式佔用的記憶體,那麼可能在一定程度上反而會降低系統性能,因為系統需要頻繁的進行記憶體和硬碟間的頁面交換。

將 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
上面是主要用到的兩個函式,加上去後程式,效果非常好: