.Net Discovery系列-深入理解平臺機制與性能影響(上)

作者: Aicken(李鳴)  來源: 博客園  發布時間: 2011-04-24 21:52  閱讀: 1243 次  推薦: 0   原文鏈接   [收藏]  
摘要:在本文中將對以前所講的.Net平臺知識做一個小小的總結與機制分析,引出并重點介紹這些機制對程序性能的影響與改進建議。

  轉眼間《.Net Discovery》系列文章已經推出1年了,本文為該系列的第10-13篇文章,在本文中將對以前所講的.Net平臺知識做一個小小的總結與機制分析,引出并重點介紹這些機制對程序性能的影響與改進建議。

  本文將分為四部分,分別講述了:垃圾回收機制、即時編譯機制、異常處理機制、字符串駐駐留機制的原理與性能改進建議。

  《.Net Discovery》系列的每篇文章撰寫耗時都在2天以上,轉載時麻煩著名作者Aicken(李鳴),并且未經作者同意,禁止一切商業用途!

  一.關于垃圾回收機制●

  機制分析垃圾收集器是.Net平臺的一個特性,它自動回收托管堆上不再使用的對象,及時清理內存,這一切都是對開發人員透明的,當然你也可以手動把它召喚出來,它的本質就是跟蹤所有被引用到的對象,整理對象不再被引用的對象,回收相應的內存。垃圾收集機制采用標記與清除(Mark Sweep)算法來完成上述任務,整個過程分為兩步:

  Step 1.Mark-Sweep :從應用程序的root出發,利用相互引用關系,遍歷其在Heap上動態分配的所有對象,指明需要回收的對象,標記出那些存活的對象,予以標記。

  Step 2.Compact: 對內存中存活的對象進行移動,修改它們的指針,使之在內存中連續,這樣空閑的內存也就連續了,即完成了內存釋放工作,也解決了內存碎片問題,這個過程也可以成為指針的壓縮。垃圾收集器一般將托管堆中的對象分為3代,這可以通過調用GC.MaxGeneration得知,對象按照存在時間長短進行分代,最短的分在第0代,最長的分在第2代,第2代中的對象往往是比較大的,第二代空間被稱作Large Object Heap,對于2代對象的回收,與第0、1代回收方式相比最大的不同在于,沒有了指針移動的壓縮過程。如下圖,第一次GC時,左邊第一列A-F表示內存中的對象,位于淺藍色 區域,經過Mark后,ACDF標記為可用,Sweep過程清除了BE,Compact過程移動了ACDF,使之位于連續存儲區域中;第二次使用綠色做標記;第三次GC使用藍色表示標記;可以看出第三次GC過程沒有了指針移動的壓縮過程。

圖1 對象的回收

  ●性能影響分析這個過程看起來有點復雜,的確垃圾收集器的啟動是會占用一些CPU時間,從而影響系統的性能,但這種影響很有限,并且這些損失是有所值的。

  1.垃圾收集器并不是沒有規律的啟動,而是當代齡達到一定觸發條件時啟動,而且垃圾收集器只是移動代齡較低的1、2代的資源,并不會移動LOH中的對象。這就在一定程度上避免了GC長時間鎖定線程導致的性能損失。

  2.GC有三種不同的工作模式,適用于不同環境的情況,并不是所有環境都是使用掛起-查找與標記-壓縮-恢復 的流程。Workstation GC with Concurrent模式可以第0、1代的收集仍然是要暫時掛起應用程序,在收集第2代時,會并行處理,具體原理是將Full GC過程切分成多個短暫子過程對線程進行凍結,在線程凍結時間之外,應用程序仍然可以正常運行。

  這主要通過將0代空間設置的很大,使Full GC時,CLR仍然能夠在0代中進行內存分配,如果Full GC時0代內存也已用盡,那么應用程序將被掛起,等待Full GC的完成。在多CPU的情況下,可以使用和Server GC模式。這種GC模式有著很高的性能和效率。

  這種模式下,CLR為每個CPU創建一個專用的GC線程,每個CPU可以獨立的為相應的heap執行GC操作,這些GC線程是以非并發的形式工作的,收集工作與線程正常工作不能同時進行,這就是說第0、1、2代的收集都會掛起應用線程。在.Net 4.0中,有一種新的垃圾收集機制,叫做后臺收集。這種機制以concurrent GC為基礎的,如上文所講,Workstation GC with Concurrent模式中,在Full GC過程時,CLR仍然能夠在0代中進行內存分配,如果Full GC時0代內存也已用盡,那么應用程序將被掛起,等待Full GC的完成。

  3.垃圾收集器是配合策略引擎工作的。策略引擎可以喚醒GC,它會根據GC啟動的次數、頻率、代齡情況等自發的啟動GC,使GC工作。特別要注意的是,由程序人員手動的調用GC收集的代碼,同樣會影響策略引擎的工作,這樣會給策略引擎錯誤的信號,從而導致GC的錯誤啟動,所以在沒有必要的情況下,一般不建議使用GC.Collect();手動回收。

  ● 綜述比起垃圾收集器帶來的微乎的性能損失,我們應該把精力放在程序的優化上,非托管資源的及時釋放、字符串拼接、循環內的業務代碼都是需要注意的地方。垃圾收集機制不是.Net也不是Java的專利,它已經有一段進化的歷史,越來越多的案例也證明垃圾收集機制的優點,Exchange 2010的大部分模塊就是基于托管環境的。

  二.關于實時編譯機制JIT(Just In Time簡稱JIT)是.Net邊運行邊編譯的一種機制,這種機制的命名來源于豐田汽車在20世紀60年代實行的一種生產方式,中文譯為準時制。.Net 的JIT編譯器在設計初衷和運行方式來上講,都與豐田汽車的這種準時生產思想體系有著很大的相似之處,所以讓我們先來透過準時生產方式來理解.Net的JIT機制吧。

  準時生產的基本思想可概括為在需要的時候,按需要的量生產所需的產品,這正是.Net JIT編譯器的設計初衷,即在需要的時候編譯需要的代碼。

  相關文章:.Net Discovery系列之-深入理解平臺機制與性能影響 (中) 

                       .Net Discovery系列-深入理解平臺機制與性能影響(上)

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()