相關閱讀 |
>>> 技術話題—商業文明的嶄新時代 >>> | 簡體 傳統 |
今天查看一個同事的代碼,發現代碼中多處地方使用了GC.Collect()方法,我問他為什么這么做,他說感覺程序中定義了好多變量,怕GC回收不及時,用GC.Collect()可以手動掌控GC進行垃圾回收。 先不說他對GC的垃圾回收機制還不了解,就是調用GC.Collect()后GC真的會不會回收這個問題都需要再深入了解一下。 下面我們通過一個小例子,來看一下使用GC.Collect后的內存情況。 我們知道可以通過GCHandle設置引用類型(可直接復制到本機結構中的類型)在GC垃圾回收時不移動地址,并且獲取地址值,那么就可以通過在兩次地址獲取中間加入Collect方法,來判斷GC是否真的進行了垃圾回收。 我們發現地址并沒有變化! 修改一下代碼使用for循環生成多個object: 重新編譯后,執行結果如下: 地址變了! 通過上面的代碼,我們知道GC.Collect并不是只要執行就會進行垃圾回收,實際上GC會首先判斷當前是不是真的需要進行回收,如果內存中只有很小的垃圾(碎片化不嚴重)時,這時候啟動回收顯然得不償失,影響性能。 1. 永遠都不要手動進行GC.Collect操作。如果你認為有,需要檢查你地代碼 2. 即使當你手動進行垃圾回收時,GC還不會立即執行,它要先判斷是否真正需要回收前言
GC.Collect
using System;using System.Runtime.InteropServices;namespace TestGCCollect
{class Program
{static void Main(string[] args)
{//創建一個沒有引用的垃圾對象new object();//這是我們要判定地址的對象int[] gcTest = new int[10]; //設定Pinned通知GC在進行回收的時候不移動地址GCHandle gcHandle1 = GCHandle.Alloc(gcTest, GCHandleType.Pinned);//獲取gcTest在堆中的地址并輸出IntPtr add1 = gcHandle1.AddrOfPinnedObject();
Console.WriteLine(add1.ToString());//通知GC當程序返回的時候可以回收 gcHandle1.Free(); //調用GC回收object垃圾 GC.Collect(); //再次獲取地址GCHandle gcHandle2 = GCHandle.Alloc(gcTest, GCHandleType.Pinned);
IntPtr add2 = gcHandle2.AddrOfPinnedObject();
Console.WriteLine(add2.ToString());
gcHandle2.Free();
Console.ReadKey();
}
}
}
//創建沒有引用的垃圾對象for (int i = 0; i < 30000; i++)new object();//這是我們要判定地址的對象int[] gcTest = new int[10];
總結
Cnblogs quinn.hong 2015-08-23 08:57:30
稱謂:
内容: