不得不知的CLR中的GC

引言

GC 做爲CLR的垃圾回收器,讓程序員能夠把更多的關注度放在業務上而不是垃圾回收(內存回收)上。其實不少語言也有相似的東東,html

如Java也有JIT 等等程序員

 

GC基本概念

  • 垃圾回收機制的算法有好多種,GC爲Mark-Sweep算法。
  • GC中分爲三代,來優化管理不一樣生命週期的對象。
  • 大部分的對象在Gen0就死掉了。
  • Gen0 和Gen 1 又叫做ephemeral generations (短命代,我的翻譯意見 )
  • 大於85,000bytes的對象會被直接分配到Large object heap上,且在Gen2回收時纔會被回收

8

 

GC回收時機

  1. 系統內存不足
  2. Gen0 沒有足夠的空間須要申請新的空間(應該是segment)
  3. 手動條用GC.Collect()

 

GC步驟

當進行一次垃圾回收操做時,會分三個步驟進行:
1. 先假設全部對象都是垃圾;
2. 標記出正在使用的對象; (會先找GC Roots,而後遍歷GC Heap上的每一個對象,生成一個對象List)
標記依據:
     a. 被變量引用的對象,仍然在做用域中。
     好比某個類中的某個方法,方法執行了一半,若是此時發生垃圾回收,那麼方法塊中的變量都在做用域中,那麼它們都會被標記爲正在使用。
     b. 被另外一個對象引用的對象,仍在使用中。
3. 壓縮:釋放第二步中未標記的對象(再也不使用,即「垃圾」)並將使用中的對象轉移到連續的內存塊中。
只要垃圾回收器釋放了能釋放的對象,它就會壓縮剩餘的對象,把它們都移回堆的端部,再一次造成一個連續的塊。(這裏其實有個更新引用或者說指針的操做)算法

 

GC處理Finalizalbe對象工做原理

 

10

 

上圖假設是新建立對象爲Gen0 代的且爲Finalizable的對象,首次就會被回收(如局部的且<85,000bytes的對象)。編程

實現 Finalize 方法或析構函數對性能可能會有負面影響,所以應避免沒必要要地使用它們。用 Finalize 方法回收對象使用的內存須要至少兩次垃圾回收。當垃圾回收器執行回收時,它只回收沒有終結器的不可訪問對象的內存。這時,它不能回收具備終結器的不可訪問對象。它改成將這些對象的項從終止隊列中移除並將它們放置在標爲準備終止的對象列表中。該列表中的項指向託管堆中準備被調用其終止代碼的對象。垃圾回收器爲此列表中的對象調用 Finalize 方法,而後,將這些項從列表中移除。後來的垃圾回收將肯定終止的對象確實是垃圾,由於標爲準備終止對象的列表中的項再也不指向它們。在後來的垃圾回收中,實際上回收了對象的內存。性能優化

 

GC分類

從工做模式角度來看:多線程

兩大類:WorkStation GC Server GC併發

分類依據:app

WorkStation GC 是默認的工做方式,若是你是單處理器的機器,那麼這是你惟一的選擇,而且及時你配置了Concurrent選項爲True,也不會生效函數

Server GC 在多處理器的機器上纔會出現,且默認出如今Aps.net寄存服務中。他會爲每一個處理器都建立一個GC Heap,而且會並行執行回收操做。該模式的GC能夠最大化吞吐量和較好的收縮性(4處理器+)post

 

<configuration>
  <runtime>
    <gcServer enabled="true" />
  </runtime>
</configuration>

能夠經過以上配置方式或者經過native code 類指定GC 工做模式

HRESULT CorBindToRuntimeEx( LPWSTR pwszVersion,
  LPWSTR pwszBuildFlavor, // use 「svr」 for server mode,
  // 「wks」 or NULL for workstation
  DWORD flags,
  REFCLSID rclsid,
  REFIID riid,
  LPVOID* ppv );

下表爲GC爲GC heap向系統申請時的基本單位Segment的默認值注意是默認值,這些值會隨着程序的實際執行狀況,GC動態調整。這裏瞭解下便可,另外正是因爲有segment的概念因此回出現內存碎片的問題,因此GC在垃圾回收過程當中會進行內存整理,以減小內存碎片,提升內存使用率。

 

32-bit

64-bit

Workstation GC

16 MB

256 MB

Server GC

64 MB

4 GB

Server GC with > 4 logical CPUs

32 MB

2 GB

Server GC with > 8 logical CPUs

16 MB

1 GB

 

從工做方式,工做側重點和實現上來看:

兩類:Foreground GCConcurrent GC | BackGround GC(側重於Gen2 GC性能優化,正常狀況Gen0 ,Gen1的速度都比較快)

Foreground GC工做的時候絕對是.net 程序要向系統申請分配Gc Heap空間啦,因此它的優先級最高。一旦它運行,其餘全部線程都會被掛起來。

 

經過配置文件開啓或者關閉併發和後臺模式,(同一個配置項)

<configuration>
<runtime>
   <gcConcurrent enabled="false" />
</runtime>
</configuration

 

In workstation or server garbage collection, you can enable concurrent garbage collection , which enables threads to run concurrently with a dedicated thread that performs the garbage collection for most of the duration of the collection. This option affects only garbage collections in generation 2; generations 0 and 1 are always non-concurrent because they finish very fast.


Server GC 和Workstation GC均可以開啓併發GC。在GC回收的過程當中大部分時間用戶線程能夠併發運行。但這中效果只能影響到2帶GC的過程,由於0代1代的時間過短了。

 

 

  Concurrent WS Non-Concurrent WS BackGround WS
(替代併發)
Server GC Server GC Background(替代併發)
出現時間 .net 1+ .net 1+<x<.net.4 .net 4+ .net 1+ .net 4.5.1+
設計目標 在吞吐量和界面相應速度上尋找平衡點 最大化吞吐量 在WS的設計基礎上,優化gen2 GC性能 多處理器機器上使用多線程處理相同類型的請求以便最大化服務程序吞吐量 優化gen2 GC性能
GC Heap數量 1 1 1 1 per processor (HT aware) 1 per processor (HT aware)
GC threads 分配空間的線程會觸發GC, 分配空間的線程會觸發GC線程   每一個處理器都有一個專職的GC線程 每一個處理器都有一個專職的GC background線程
GC線程優先權 和工做線程具備相同的優先權 和工做線程具備相同的優先權 background GC線程與工做線程有相同優先級,但都低於前臺GC線程 THREAD_PRIORITY_HIGHEST background GC線程與工做線程有相同優先級,但都低於前臺GC線程
工做線程(非GC線程) GC工做過程當中短暫屢次掛起 GC工做過程當中一直被掛起 GC工做過程當中短暫屢次掛起,較併發性能更加(針對Gen2的) GC工做過程當中會被掛起 GC工做過程當中短暫屢次掛起,較併發性能更加(針對Gen2的)
ephemeral generation 的前臺GC工做時會掛起其餘全部線程
配置方式 <gcConcurrent enabled="true"> <gcConcurrent enabled="false"> <gcConcurrent enabled="false"> <gcServer enabled="true"> <gcConcurrent enabled="false">
是否會超時       不會

 

----------------------------------------------------------------------------------------------
 

image

Workstation GC

-------------------------------------------------------------------------------------------------

image

Server garbage collection

-------------------------------------------------------------------------------------------------

image
Concurrent garbage collection

-------------------------------------------------------------------------------------------------

image

Background workstation garbage collection

-------------------------------------------------------------------------------------------------

image

Background server garbage collection

-------------------------------------------------------------------------------------------------

 

其餘相關

 

編程的內存模型中咱們會接觸到「堆」和「棧」兩個部分。每一個線程都有本身的棧,但共享堆(固然不是直接跨線程訪問的意思,只能理解爲共存在堆上)。

 

性能計數

What is the cost of a garbage collection? How can I keep this cost at a minimum?

You can measure the GC cost for your application with a few different counters. Remember that all of these counters are updated at the end of a collection which means that if you use averages they may not be valid after a long time of inactivity.

.NET CLR Memory\% time in GC - This counter measures the amount of CPU time you spend in GC and it is calculated as (CPU time for GC/CPU time since last GC)

.NET CLR Memory\# Induced GC – This is the number of garbage collections that have occurred as a result of someone calling GC.Collect(). Ideally this should be 0 since inducing full collections means that you spend more time in the GC, and also because the GC continuously adapts itself to the allocation patterns in the application, and performing manual GCs skews this optimization.

.NET CLR Memory\# Gen X collections – This counter displays the amount of collections that have been performed for a given generation. Since the cost of gen 2 collections is high compared to Gen 1 and Gen 0 you want to have as few Gen 2 collections per Gen 1 and Gen 0 collections as possible. A ratio of 1:10:100 is pretty good.

The most common causes for high CPU in GC or a high number of Gen 2 collections compared to 1 and 0 is high allocation of large objects and letting objects survive multiple generations because of improper use of finalizers or because finalizable objects are not disposed of correctly in the application.

參考

Finding garbage

.NET垃圾回收 – 原理淺析

How does the GC work and what are the sizes of the different generations?

垃圾回收

C#技術漫談之垃圾回收機制(GC)

託管堆與垃圾收集

關於CLR內存管理一些深層次的討論

http://blogs.msdn.com/maoni/archive/2004/06/15/156626.aspx

http://blogs.msdn.com/maoni/archive/2004/09/25/234273.aspx

 

垃圾回收翻譯系列(√)

相關文章
相關標籤/搜索