GC(垃圾回收)必須Stop-the-world?

GC(垃圾回收)必須Stop-the-world?html

併發編程的許多困難都源於對象生存期問題,當對象在線程之間傳遞時,要確保它們安全地釋放就變得很麻煩。所以GC可使得併發編程變得容易。可是實GC也是一個挑戰,可是一次實現,就能夠解決人們手動管理內存的麻煩(C語言),大大提升的開發效率和避免了許多Bug。java

可是GC也是有成本的,他會影響程序的效率,GC是一個很是挑戰的工做,不少計算機科學家在上面耗費了數十年不斷的提高效率。算法

GC算法設計時,會考慮幾個重要指標:編程

  • 程序吞吐量:GC對程序效率的影響,也就花費在GC的時間和程序處理正常業務的時間比;
  • GC吞吐量:單位時間內垃圾回收的數量;
  • 暫停時間:Stop-the-world 的時間;
  • 併發:垃圾回收機制如何使用多核;
  • 等等還有不少

不少人問爲何GC的時候要暫停(Stop-the-world)整個程序,爲何不能併發的執行GC呢?GC本質上是一種權衡,Stop-the-world 是爲了GC吞吐量(在給定CPU時間內多少垃圾能夠被收集器清除?),便不是說GC必須STW,你也能夠選擇下降運行速度可是能夠併發執行的收集算法,這取決於你的業務。安全

J9VM中標記階段有描述,標記分爲:bash

  • 並行標記
    並行標記的目的是在不下降單處理器系統上標記性能的狀況下,提升多處理器系統上典型標記的性能。
    
      經過增長共享使用工做包池的助手線程,能夠提升對象標記的性能。例如,可選取由一個線程返回給池的完整輸出包做爲另外一個線程的新輸入包。
    
      並行標記仍須要一個用做主協調代理進程的應用程序線程的參與。助手線程幫助標識回收的根指針並跟蹤這些根。標記位是使用不須要附加鎖的主機原子原語來更新的
    複製代碼
  • 併發標記
    在堆大小增長時,併發標記可以提供縮短且一致的垃圾回收暫停時間。
    
      在堆滿以前,GC 將啓動併發標記階段。在併發階段,GC 掃描堆,檢查根對象,好比堆棧、JNI 引用和類靜態字段。經過要求每一個線程掃描本身的堆棧來掃描堆棧。隨後,這些根將用於併發跟蹤活動對象。在線程執行堆鎖分配時,跟蹤由低優先級的後臺線程和每一個應用程序線程執行。
    
      當 GC 利用正在運行的應用程序線程併發標記活動對象時,必須記錄對已跟蹤對象的任何更改。它使用在每次更新對象中的引用時運行的寫屏障。在發生對象引用更新時,寫屏障將使用標誌。使用該標誌迫使對部分堆從新掃描。
    複製代碼

好比:你作金融交易類的項目,分秒必爭,那能夠選擇並行的方式。若是你是一種後臺任務,好比數據處理,那你能夠選擇STW類型算法,使 GC 的吞吐量獲得最高。markdown

兩類算法最終的權衡指標就GC效率:程序工做時間與執行收集時間的比率。併發

沒有單一的算法在全部方面都完美,語言也不可能知道程序的業務類型,這也就是「GC調優」存在的緣由。這也是科學的基礎規律。oop

相關文章
相關標籤/搜索