一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

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

 賈朋亮博客 2014-09-27
GC,Garbage Collect,中文意思就是垃圾回收,指的是系統(tǒng)中的內(nèi)存的分配和回收管理。其對(duì)系統(tǒng)性能的影響是不可小覷的。今天就來說一下關(guān)于GC優(yōu)化的東西,這里并不著重說概念和理論,主要說一些實(shí)用的東西。關(guān)于概念和理論這里只做簡(jiǎn)單說明,具體的大家可以看微軟官方文檔。

一、什么是GC

  GC如其名,就是垃圾收集,當(dāng)然這里僅就內(nèi)存而言。Garbage Collector(垃圾收集器,在不至于混淆的情況下也成為GC)以應(yīng)用程序的root為基礎(chǔ),遍歷應(yīng)用程序在Heap上動(dòng)態(tài)分配的所有對(duì)象[2],通過識(shí)別它們是否被引用來確定哪些對(duì)象是已經(jīng)死亡的、哪些仍需要被使用。已經(jīng)不再被應(yīng)用程序的root或者別的對(duì)象所引用的對(duì)象就是已經(jīng)死亡的對(duì)象,即所謂的垃圾,需要被回收。這就是GC工作的原理。為了實(shí)現(xiàn)這個(gè)原理,GC有多種算法。比較常見的算法有Reference Counting,Mark Sweep,Copy Collection等等。目前主流的虛擬系統(tǒng).NET CLR,Java VM和Rotor都是采用的Mark Sweep算法。(此段內(nèi)容來自網(wǎng)絡(luò))

.NET的GC機(jī)制有這樣兩個(gè)問題:

  首先,GC并不是能釋放所有的資源。它不能自動(dòng)釋放非托管資源。

  第二,GC并不是實(shí)時(shí)性的,這將會(huì)造成系統(tǒng)性能上的瓶頸和不確定性。

  GC并不是實(shí)時(shí)性的,這會(huì)造成系統(tǒng)性能上的瓶頸和不確定性。所以有了IDisposable接口,IDisposable接口定義了Dispose方法,這個(gè)方法用來供程序員顯式調(diào)用以釋放非托管資源。使用using語句可以簡(jiǎn)化資源管理。

二、托管資源和非托管資源

  托管資源指的是.NET可以自動(dòng)進(jìn)行回收的資源,主要是指托管堆上分配的內(nèi)存資源。托管資源的回收工作是不需要人工干預(yù)的,有.NET運(yùn)行庫在合適調(diào)用垃圾回收器進(jìn)行回收。

非托管資源指的是.NET不知道如何回收的資源,最常見的一類非托管資源是包裝操作系統(tǒng)資源的對(duì)象,例如文件,窗口,網(wǎng)絡(luò)連接,數(shù)據(jù)庫連接,畫刷,圖標(biāo)等。這類資源,垃圾回收器在清理的時(shí)候會(huì)調(diào)用Object.Finalize()方法。默認(rèn)情況下,方法是空的,對(duì)于非托管對(duì)象,需要在此方法中編寫回收非托管資源的代碼,以便垃圾回收器正確回收資源。

在.NET中,Object.Finalize()方法是無法重載的,編譯器是根據(jù)類的析構(gòu)函數(shù)來自動(dòng)生成Object.Finalize()方法的,所以對(duì)于包含非托管資源的類,可以將釋放非托管資源的代碼放在析構(gòu)函數(shù)。

三、關(guān)于GC優(yōu)化的一個(gè)例子

  正常情況下,我們是不需要去管GC這些東西的,然而GC并不是實(shí)時(shí)性的,所以我們的資源使用完后,GC什么時(shí)候回收也是不確定的,所以會(huì)帶來一些諸如內(nèi)存泄漏、內(nèi)存不足的情況,比如我們處理一個(gè)約500M的大文件,用完后GC不會(huì)立刻執(zhí)行清理來釋放內(nèi)存,因?yàn)镚C不知道我們是否還會(huì)使用,所以它就等待,先去處理其他的東西,過一段時(shí)間后,發(fā)現(xiàn)這些東西不再用了,才執(zhí)行清理,釋放內(nèi)存。

  下面,來介紹一下GC中用到的幾個(gè)函數(shù):

  GC.SuppressFinalize(this); //請(qǐng)求公共語言運(yùn)行時(shí)不要調(diào)用指定對(duì)象的終結(jié)器。

  GC.GetTotalMemory(false); //檢索當(dāng)前認(rèn)為要分配的字節(jié)數(shù)。 一個(gè)參數(shù),指示此方法是否可以等待較短間隔再返回,以便系統(tǒng)回收垃圾和終結(jié)對(duì)象。

  GC.Collect(); //強(qiáng)制對(duì)所有代進(jìn)行即時(shí)垃圾回收。

GC運(yùn)行機(jī)制

  寫代碼前,我們先來說一下GC的運(yùn)行機(jī)制。大家都知道GC是一個(gè)后臺(tái)線程,他會(huì)周期性的查找對(duì)象,然后調(diào)用Finalize()方法去消耗他,我們繼承IDispose接口,調(diào)用Dispose方法,銷毀了對(duì)象,而GC并不知道。GC依然會(huì)調(diào)用Finalize()方法,而在.NET 中Object.Finalize()方法是無法重載的,所以我們可以使用析構(gòu)函數(shù)來阻止重復(fù)的釋放。我們調(diào)用完Dispose方法后,還有調(diào)用GC.SuppressFinalize(this) 方法來告訴GC,不需要在調(diào)用這些對(duì)象的Finalize()方法了。

  下面,我們新建一個(gè)控制臺(tái)程序,加一個(gè)Factory類,讓他繼承自IDispose接口,代碼如下:

復(fù)制代碼
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>();

      //拼接字符串,創(chuàng)造一些內(nèi)存垃圾
      public void MakeSomeGarbage()
      {
         for (int i = 0; i < 50000; i++)
         {
            sb.Append(i.ToString());
         }
      }

      //銷毀類時(shí),會(huì)調(diào)用析構(gòu)函數(shù)
      ~Factory()
      {
         Dispose(false);
      }

      public void Dispose()
      {
         Dispose(true);
      }

      protected virtual void Dispose(bool disposing)
      {
         if (!disposing)
         {
            return;
         }
         sb = null;
         GC.Collect();
         GC.SuppressFinalize(this);
      }
   }
}
復(fù)制代碼

只有繼承自IDispose接口,使用這個(gè)類時(shí)才能使用Using語句,在main方法中寫如下代碼:

復(fù)制代碼
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();
      }
   }
}
復(fù)制代碼

運(yùn)行結(jié)果如下,可以看到資源運(yùn)行MakeSomeGarbage()函數(shù)后的內(nèi)存占用為1796KB,釋放后成了83Kb.

代碼運(yùn)行機(jī)制:

  我們寫了Dispose方法,還寫了析構(gòu)函數(shù),那么他們分別什么時(shí)候被調(diào)用呢?我們分別在兩個(gè)方法上面下斷點(diǎn)。調(diào)試運(yùn)行,你會(huì)發(fā)現(xiàn)先走到了Dispose方法上面,知道程序運(yùn)行完也沒走析構(gòu)函數(shù),那是因?yàn)槲覀冋{(diào)用了GC.SuppressFinalize(this)方法,如果去掉這個(gè)方法后,你會(huì)發(fā)現(xiàn)先走Dispose方法,后面又走析構(gòu)函數(shù)。所以,我們可以得知,如果我們調(diào)用Dispose方法,GC就會(huì)調(diào)用析構(gòu)函數(shù)去銷毀對(duì)象,從而釋放資源。

四、什么時(shí)候該調(diào)用GC.Collect

  這里為了讓大家看到效果,我顯示調(diào)用的GC.Collect()方法,讓GC立刻釋放內(nèi)存,但是頻繁的調(diào)用GC.Collect()方法會(huì)降低程序的性能,除非我們程序中某些操作占用了大量內(nèi)存需要馬上釋放,才可以顯示調(diào)用。下面是官方文檔中的說明:

  垃圾回收 GC 類提供 GC.Collect 方法,您可以使用該方法讓應(yīng)用程序在一定程度上直接控制垃圾回收器。通常情況下,您應(yīng)該避免調(diào)用任何回收方法,讓垃圾回收器獨(dú)立運(yùn)行。在大多數(shù)情況下,垃圾回收器在確定執(zhí)行回收的最佳時(shí)機(jī)方面更有優(yōu)勢(shì)。但是,在某些不常發(fā)生的情況下,強(qiáng)制回收可以提高應(yīng)用程序的性能。當(dāng)應(yīng)用程序代碼中某個(gè)確定的點(diǎn)上使用的內(nèi)存量大量減少時(shí),在這種情況下使用 GC.Collect 方法可能比較合適。例如,應(yīng)用程序可能使用引用大量非托管資源的文檔。當(dāng)您的應(yīng)用程序關(guān)閉該文檔時(shí),您完全知道已經(jīng)不再需要文檔曾使用的資源了。出于性能的原因,一次全部釋放這些資源很有意義。有關(guān)更多信息,請(qǐng)參見 GC.Collect 方法。
  在垃圾回收器執(zhí)行回收之前,它會(huì)掛起當(dāng)前正在執(zhí)行的所有線程。如果不必要地多次調(diào)用 GC.Collect,這可能會(huì)造成性能問題。您還應(yīng)該注意不要將調(diào)用GC.Collect 的代碼放置在程序中用戶可以經(jīng)常調(diào)用的點(diǎn)上。這可能會(huì)削弱垃圾回收器中優(yōu)化引擎的作用,而垃圾回收器可以確定運(yùn)行垃圾回收的最佳時(shí)間。

參考資料:http:///questions/538060/proper-use-of-the-idisposable-interface

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    九九九热视频最新在线| 欧美日本道一区二区三区| 神马午夜福利免费视频| 国内外免费在线激情视频| 日韩欧美高清国内精品| 99久久精品久久免费| 天堂热东京热男人天堂| 欧美小黄片在线一级观看| 福利一区二区视频在线| 亚洲国产成人av毛片国产| 久热99中文字幕视频在线| 精品香蕉一区二区在线| 亚洲午夜av久久久精品| 国产精品丝袜美腿一区二区| 蜜桃传媒在线正在播放| 国产传媒精品视频一区| 欧美国产日产综合精品| 欧美又大又黄刺激视频| 白白操白白在线免费观看| 日韩午夜老司机免费视频| 99精品国产一区二区青青| 91日韩在线视频观看| 亚洲男人的天堂就去爱| 午夜日韩在线观看视频| 老司机精品视频免费入口| 亚洲国产婷婷六月丁香| 亚洲精品国产主播一区| 免费久久一级欧美特大黄孕妇| 成年男女午夜久久久精品 | 老外那个很粗大做起来很爽| 国产女同精品一区二区| 国产肥妇一区二区熟女精品| 熟女高潮一区二区三区| 亚洲熟女诱惑一区二区| 欧美人妻少妇精品久久性色| 欧美性高清一区二区三区视频| 99久只有精品免费视频播放 | 日韩美女偷拍视频久久| av在线免费播放一区二区| 在线一区二区免费的视频| 亚洲国产一级片在线观看|