在上文[如何獲取GC的STW時間]一文中,我們聊到了如何通過監聽GC發出的診斷事件來計算STW時間。裡面只簡單的介紹了幾種GC事件和它的流程。
群裡就有小夥伴在問,那麼GC事件是什麼時候產生的?分別是代表什麼含義?
那麼在本文就通過幾個圖為大家解答一下這個問題。
在.NET中,GC其實有一些不同的工作模式,根據使用者端和伺服器可以分為如下兩種模式:
Workstation GC(工作站GC),這種模式主要是為了滿足基於UI的互動式應用程式設計的,互動式意味著GC的暫停時間要儘可能的短。因為我們不想因為觸發GC導致較長的GC停頓。
Server GC (伺服器GC),這種模式主要是為了滿足基於請求處理的WEB等型別應用程式設計的,這意味著它更側重於需要滿足大的吞吐量,零星的停頓不會對齊產生重大的影響。
另外根據GC相對於使用者執行緒的操作方式,還可以分為下面兩種方式:
Non-Concurrent(非並行GC),這種方式是一直存在於.NET中的,它適用於工作站和伺服器模式,在GC進行過程中,所有的使用者執行緒都會掛起。
Concurrent (並行GC),並行GC模式它和使用者執行緒同時工作,GC進行過程中只有少數幾個過程需要掛起使用者執行緒。所以它的實現也更加複雜,但是暫停時間會更短,效能也會更好,不過現在它已經過時,本文不會著重描述它。
Background(後臺GC),在.NET Framework 4.0以後,後臺GC取代了並行GC,它只適用於Gen2的回收,但是它可以觸發對於Gen0、Gen1的回收。根據WorkstationGC和ServerGC的模式會分別在一個或多個執行緒上執行。
其實對於我們分析GC的工作來說,上文中提到的幾個事件已經足夠使用了,讓我們再來回顧一下這些事件。
Microsoft-Windows-DotNETRuntime/GC/SuspendEEStart //開始暫停託管執行緒執行
Microsoft-Windows-DotNETRuntime/GC/SuspendEEStop //暫停託管執行緒完成
Microsoft-Windows-DotNETRuntime/GC/Start // GC開始回收
Microsoft-Windows-DotNETRuntime/GC/Stop // GC回收結束
Microsoft-Windows-DotNETRuntime/GC/RestartEEStart //恢復之前暫停的託管執行緒
Microsoft-Windows-DotNETRuntime/GC/RestartEEStop //恢復託管執行緒執行完成
為了讓大家能更清晰的看懂下面的圖,會用不同形狀和顏色的影象來代表不同的含義,如下方所示:
綠色:正在執行的使用者執行緒。
紅色:執行引擎進行執行緒凍結或執行緒恢復。
實線箭頭:正在執行的GC執行緒。
虛線箭頭:被暫停的執行緒。
黃色圓球:GC事件。
紅色圓球:標記點。
下圖是WorkStationGC(非後臺)模式的執行流程,我們假設它是在一個雙核的機器上執行(下文中都是假設在雙核機器上執行),執行過程其實就像下圖所示。
在上圖中的事件流如下所示:
- GC/SuspendEEStart
- GC/SuspendEEStop
- GC/Start
- GC/Stop
- GC/RestartEEStart
- GC/RestartEEStop
其中各個標記點分別完成了如下工作:
下圖是ServerGC(非後臺)模式的執行流程。
它與WorkstationGC模式的事件流和完成的工作都一致,唯一不同的就是它會根據當前的CPU邏輯核心數量建立單獨的GC執行緒,比如上圖就有2個GC執行緒。
另外在伺服器GC模式中,使用者執行緒還是可以作為GC執行緒來使用的,像使用者執行緒1在GC發生的時候就做了一些GC工作。
下圖是WorkstationGC(後臺)模式的執行流程,可以看到後臺模式還是相當複雜的,會短暫的暫停多次,每一次都會執行不同的操作。
除了工作執行緒GC以外,另外會有單獨的後臺GC執行緒進行後臺垃圾回收。
上圖中的事件流如下所示:
- GC/SuspendEEStart
- GC/SuspendEEStop
- GC/Start
- GC/RestartEEStart
- GC/RestartEEStop
- GC/SuspendEEStart
- GC/SuspendEEStop
- GC/RestartEEStart
- GC/RestartEEStop
- GC/SuspendEEStart
- GC/SuspendEEStop
- GC/Start
- GC/Stop
- GC/RestartEEStart
- GC/RestartEEStop
- GC/Stop
其中各個標記點完成的工作如下所示:
從上面的的流程中可以看到,後臺GC主要是通過並行+多次短暫暫停來實現提升吞吐量和降低總體的STW Time的,其內部實現是非常複雜的,有興趣的小夥伴可以直接看dotnet/runtime/gc.cpp檔案。
下圖是ServerGC(後臺)模式的執行流程。
它與WorkstationGC模式的事件流和完成的工作都一致,唯一不同的就是它會根據當前的CPU邏輯核心數量建立單獨的GC執行緒,比如上圖就有2個GC執行緒,2個後臺GC執行緒。
今天帶了解了一下.NET GC中的各個階段和事件的順序,當然這裡只是簡單的帶大家瞭解一下,要知道在任何有runtime的平臺中,GC是其中相當關鍵的東西,大家如果對GC感興趣,可以閱讀附錄中的資料。