程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 從C#垃圾回收(GC)機制中挖掘性能優化方案

從C#垃圾回收(GC)機制中挖掘性能優化方案

編輯:C#入門知識

從C#垃圾回收(GC)機制中挖掘性能優化方案


GC,Garbage Collect,中文意思就是垃圾回收,指的是系統中的內存的分配和回收管理。其對系統性能的影響是不可小觑的。今天就來說一下關於GC優化的東西,這裡並不著重說概念和理論,主要說一些實用的東西。關於概念和理論這裡只做簡單說明,具體的大家可以看微軟官方文檔。   一、什麼是GC                                                                                                  GC如其名,就是垃圾收集,當然這裡僅就內存而言。Garbage Collector(垃圾收集器,在不至於混淆的情況下也成為GC)以應用程序的root為基礎,遍歷應用程序在Heap上動態分配的所有對象[2],通過識別它們是否被引用來確定哪些對象是已經死亡的、哪些仍需要被使用。已經不再被應用程序的root或者別的對象所引用的對象就是已經死亡的對象,即所謂的垃圾,需要被回收。這就是GC工作的原理。為了實現這個原理,GC有多種算法。比較常見的算法有Reference Counting,Mark Sweep,Copy Collection等等。目前主流的虛擬系統.NET CLR,Java VM和Rotor都是采用的Mark Sweep算法。(此段內容來自網絡)   .NET的GC機制有這樣兩個問題:     首先,GC並不是能釋放所有的資源。它不能自動釋放非托管資源。     第二,GC並不是實時性的,這將會造成系統性能上的瓶頸和不確定性。     GC並不是實時性的,這會造成系統性能上的瓶頸和不確定性。所以有了IDisposable接口,IDisposable接口定義了Dispose方法,這個方法用來供程序員顯式調用以釋放非托管資源。使用using語句可以簡化資源管理。       二、托管資源和非托管資源                                                                                托管資源指的是.NET可以自動進行回收的資源,主要是指托管堆上分配的內存資源。托管資源的回收工作是不需要人工干預的,有.NET運行庫在合適調用垃圾回收器進行回收。         非托管資源指的是.NET不知道如何回收的資源,最常見的一類非托管資源是包裝操作系統資源的對象,例如文件,窗口,網絡連接,數據庫連接,畫刷,圖標等。這類資源,垃圾回收器在清理的時候會調用Object.Finalize()方法。默認情況下,方法是空的,對於非托管對象,需要在此方法中編寫回收非托管資源的代碼,以便垃圾回收器正確回收資源。            在.NET中,Object.Finalize()方法是無法重載的,編譯器是根據類的析構函數來自動生成Object.Finalize()方法的,所以對於包含非托管資源的類,可以將釋放非托管資源的代碼放在析構函數。       三、關於GC優化的一個例子                                                                               正常情況下,我們是不需要去管GC這些東西的,然而GC並不是實時性的,所以我們的資源使用完後,GC什麼時候回收也是不確定的,所以會帶來一些諸如內存洩漏、內存不足的情況,比如我們處理一個約500M的大文件,用完後GC不會立刻執行清理來釋放內存,因為GC不知道我們是否還會使用,所以它就等待,先去處理其他的東西,過一段時間後,發現這些東西不再用了,才執行清理,釋放內存。     下面,來介紹一下GC中用到的幾個函數:     GC.SuppressFinalize(this); //請求公共語言運行時不要調用指定對象的終結器。     GC.GetTotalMemory(false); //檢索當前認為要分配的字節數。 一個參數,指示此方法是否可以等待較短間隔再返回,以便系統回收垃圾和終結對象。     GC.Collect();  //強制對所有代進行即時垃圾回收。   GC運行機制     寫代碼前,我們先來說一下GC的運行機制。大家都知道GC是一個後台線程,他會周期性的查找對象,然後調用Finalize()方法去消耗他,我們繼承IDispose接口,調用Dispose方法,銷毀了對象,而GC並不知道。GC依然會調用Finalize()方法,而在.NET 中Object.Finalize()方法是無法重載的,所以我們可以使用析構函數來阻止重復的釋放。我們調用完Dispose方法後,還有調用GC.SuppressFinalize(this) 方法來告訴GC,不需要在調用這些對象的Finalize()方法了。     下面,我們新建一個控制台程序,加一個Factory類,讓他繼承自IDispose接口,代碼如下:   復制代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text;   namespace GarbageCollect {    public class Factory : IDisposable    {       private StringBuilder sb = new StringBuilder();       List<int> list = new List<int>();         //拼接字符串,創造一些內存垃圾       public void MakeSomeGarbage()       {          for (int i = 0; i < 50000; i++)          {             sb.Append(i.ToString());          }       }         //銷毀類時,會調用析構函數       ~Factory()       {          Dispose(false);       }         public void Dispose()       {          Dispose(true);       }         protected virtual void Dispose(bool disposing)       {          if (!disposing)          {             return;          }          sb = null;          GC.Collect();          GC.SuppressFinalize(this);       }    } } 復制代碼 只有繼承自IDispose接口,使用這個類時才能使用Using語句,在main方法中寫如下代碼:   復制代碼 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics;   namespace GarbageCollect {    class Program    {       static void Main(string[] args)       {          using(Factory f = new Factory())          {             f.MakeSomeGarbage();             Console.WriteLine("Total memory is {0} KBs.", GC.GetTotalMemory(false) / 1024);          }            Console.WriteLine("After GC total memory is {0} KBs.", GC.GetTotalMemory(false) / 1024);                    Console.Read();       }    } } 復制代碼 運行結果如下,可以看到資源運行MakeSomeGarbage()函數後的內存占用為1796KB,釋放後成了83Kb.           代碼運行機制:     我們寫了Dispose方法,還寫了析構函數,那麼他們分別什麼時候被調用呢?我們分別在兩個方法上面下斷點。調試運行,你會發現先走到了Dispose方法上面,知道程序運行完也沒走析構函數,那是因為我們調用了GC.SuppressFinalize(this)方法,如果去掉這個方法後,你會發現先走Dispose方法,後面又走析構函數。所以,我們可以得知,如果我們調用Dispose方法,GC就會調用析構函數去銷毀對象,從而釋放資源。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved