1. 程式人生 > >GC 知識點補充——CMS

GC 知識點補充——CMS

之前已經講過了不少有關 GC 的內容,今天準備將之前沒有細講的部分進行補充,首先要提到的就是垃圾收集器。

基礎的回收方式有三種:清除壓縮複製,衍生出來的垃圾收集器有:

Serial 收集器

新生代收集器,使用停止複製演算法,使用一個執行緒進行 GC ,序列,其它工作執行緒暫停。

使用-XX:+UseSerialGC開關來控制使用Serial + Serial Old模式執行進行記憶體回收(這也是虛擬機器在 Client 模式下執行的預設值)。

ParNew 收集器

新生代收集器,使用停止複製演算法,Serial 收集器的多執行緒版,用多個執行緒進行 GC ,並行,其它工作執行緒暫停,關注縮短垃圾收集時間。

使用-XX:+UseParNewGC開關來控制使用ParNew + Serial Old收集器組合收集記憶體;使用-XX:ParallelGCThreads來設定執行記憶體回收的執行緒數。

Parallel Scavenge 收集器

新生代收集器,使用停止複製演算法,關注 CPU 吞吐量,即執行使用者程式碼的時間/總時間,比如:JVM 執行 100 分鐘,其中執行使用者程式碼 99 分鐘,垃 圾收集 1 分鐘,則吞吐量是 99% ,這種收集器能最高效率的利用 CPU ,適合執行後臺運算(其他關注縮短垃圾收集時間的收集器,如 CMS ,等待時間很少,所以適 合用戶互動,提高使用者體驗)。

使用-XX:+UseParallelGC

開關控制使用Parallel Scavenge + Serial Old收集器組合回收垃圾(這也是在 Server 模式下的預設值);使用-XX:GCTimeRatio來設定使用者執行時間佔總時間的比例,預設 99 ,即 1% 的時間用來進行垃圾回收。使用-XX:MaxGCPauseMillis設定 GC 的最大停頓時間(這個引數只對 Parallel Scavenge 有效),用開關引數-XX:+UseAdaptiveSizePolicy可以進行動態控制,如自動調整 Eden / Survivor 比例,老年代物件年齡,新生代大小等,這個引數在 ParNew 下沒有。

Serial Old 收集器

老年代收集器,單執行緒收集器,序列,使用標記-整理演算法,使用單執行緒進行GC,其它工作執行緒暫停(注意:在老年代中進行標記-整理演算法清理,也需要暫停其它執行緒),在JDK1.5之前,Serial Old 收集器與 ParallelScavenge 搭配使用。

整理的方法是 Sweep (清除)和 Compact (壓縮),清除是將廢棄的物件幹掉,只留倖存的物件,壓縮是移動物件,將空間填滿保證記憶體分為2塊,一塊全是物件,一塊空閒),

Parallel Old 收集器

老年代收集器,多執行緒,並行,多執行緒機制與 Parallel Scavenge 差不錯,使用標記-整理演算法,在 Parallel Old 執行時,仍然需要暫停其它工作執行緒。

Parallel Old 收集器的整理,與 Serial Old 不同,這裡的整理是Copy(複製)和Compact(壓縮),複製的意思就是將倖存的物件複製到預先準備好的區域,而不是像Sweep(清除)那樣清除廢棄的物件。

Parallel Old 在多核計算中很有用。 Parallel Old 出現後(JDK 1.6),與 Parallel Scavenge 配合有很好的效果,充分體現 Parallel Scavenge 收集器吞吐量優先的效果。使用-XX:+UseParallelOldGC開關控制使用Parallel Scavenge + Parallel Old組合收集器進行收集。

CMS

全稱 Concurrent Mark Sweep,老年代收集器,致力於獲取最短回收停頓時間(即縮短垃圾回收的時間),使用標記-清除演算法,多執行緒,優點是併發收集(使用者執行緒可以和 GC 執行緒同時工作),停頓小。

使用-XX:+UseConcMarkSweepGC進行ParNew + CMS + Serial Old進行記憶體回收,優先使用ParNew + CMS(原因見後面),當用戶執行緒記憶體不足時,採用備用方案Serial Old收集。

如何開始

首先來看一下 CMS 是在什麼情況下進行 GC:

  1. 首先 JVM 根據-XX:CMSInitiatingOccupancyFraction-XX:+UseCMSInitiatingOccupancyOnly來決定什麼時間開始垃圾收集。
  2. 如果設定了-XX:+UseCMSInitiatingOccupancyOnly,那麼只有當老年代佔用確實達到了-XX:CMSInitiatingOccupancyFraction引數所設定的比例時才會觸發 CMS GC。
  3. 如果沒有設定-XX:+UseCMSInitiatingOccupancyOnly,那麼系統會根據統計資料自行決定什麼時候觸發 CMS GC。因此有時會遇到設定了 80% 比例才 CMS GC,但是 50% 時就已經觸發了,就是因為這個引數沒有設定的原因。

具體執行

CMS GC 的執行過程,具體來說就是:

初始標記(CMS-initial-mark)

該階段是 stop the world 階段,因此此階段標記的物件只是從 root 集最直接可達的物件。

此階段會列印 1 條日誌:CMS-initial-mark:961330K(1572864K),指標記時,老年代的已用空間和總空間

併發標記(CMS-concurrent-mark)

此階段是和應用執行緒併發執行的,所謂併發收集器指的就是這個,主要作用是標記可達的物件,此階段不需要使用者執行緒停頓。

此階段會列印 2 條日誌:CMS-concurrent-mark-start,CMS-concurrent-mark

預清理(CMS-concurrent-preclean)

此階段主要是進行一些預清理,因為標記和應用執行緒是併發執行的,因此會有些物件的狀態在標記後會改變,此階段正是解決這個問題。因為之後的 CMS-remark 階段也會 stop the world,為了使暫停的時間儘可能的小,也需要 preclean 階段先做一部分工作以節省時間。

此階段會列印 2 條日誌:CMS-concurrent-preclean-start,CMS-concurrent-preclean

可控預清理(CMS-concurrent-abortable-preclean)

此階段的目的是使 CMS GC 更加可控一些,作用也是執行一些預清理,以減少 CMS-remark 階段造成應用暫停的時間。

此階段涉及幾個引數:

    -XX:CMSMaxAbortablePrecleanTime:當 abortable-preclean 階段執行達到這個時間時才會結束。
    -XX:CMSScheduleRemarkEdenSizeThreshold(預設2m):控制 abortable-preclean 階段什麼時候開始執行,即當年輕代使用達到此值時,才會開始 abortable-preclean 階段。
    -XX:CMSScheduleRemarkEdenPenetratio(預設50%):控制 abortable-preclean 階段什麼時候結束執行。

此階段會列印 3 條日誌:CMS-concurrent-abortable-preclean-start,CMS-concurrent-abortable-preclean,CMS:abort preclean due to time XXX

重新標記(CMS-remark)

此階段暫停應用執行緒,停頓時間比並發標記小得多,但比初始標記稍長,因為會對所有物件進行重新掃描並標記。

此階段會列印以下日誌:

  1. YG occupancy:964861K(2403008K),指執行時年輕代的情況。
  2. CMS remark:961330K(1572864K),指執行時老年代的情況。
  3. 此外,還打印出了弱引用處理、類解除安裝等過程的耗時。

併發清除(CMS-concurrent-sweep)

此階段進行併發的垃圾清理。

併發重設狀態等待下次CMS的觸發(CMS-concurrent-reset)

此階段是為下一次 CMS GC 重置相關資料結構。

總結

CMS 的收集過程,概括一下就是:2 次標記,2 次預清除,1 次重新標記,1 次清除。

在CMS清理過程中,只有初始標記和重新標記需要短暫停頓使用者執行緒,併發標記和併發清除都不需要暫停使用者執行緒,因此效率很高,很適合高互動的場合。

CMS也有缺點,它需要消耗額外的 CPU 和記憶體資源。在 CPU 和記憶體資源緊張,會加重系統負擔(CMS 預設啟動執行緒數為( CPU數量 + 3 ) / 4 )。

另外,在併發收集過程中,使用者執行緒仍然在執行,仍然產生記憶體垃圾,所以可能產生“浮動垃圾”(本次無法清理,只能下一次Full GC才清理)。因此在 GC 期間,需要預留足夠的記憶體給使用者執行緒使用。

所以使用 CMS 的收集器並不是老年代滿了才觸發 Full GC ,而是在使用了一大半(預設 68% ,即 2/3 ,使用-XX:CMSInitiatingOccupancyFraction來設定)的時候就要進行 Full GC。如果使用者執行緒消耗記憶體不是特別大,可以適當調高-XX:CMSInitiatingOccupancyFraction以降低 GC 次數,提高效能。如果預留的使用者執行緒記憶體不夠,則會觸發 Concurrent Mode Failure,此時,將觸發備用方案:使用 Serial Old 收集器進行收集,但這樣停頓時間就長了,因此-XX:CMSInitiatingOccupancyFraction不宜設的過大。

還有,CMS 採用的是標記-清除演算法,會導致記憶體碎片的產生,可以使用-XX:+UseCMSCompactAtFullCollection來設定是否在 Full GC 之後進行碎片整理,用-XX:CMSFullGCsBeforeCompaction來設定在執行多少次不壓縮的 Full GC 之後,來一次帶壓縮的 Full GC。

併發和並行

併發收集:

指使用者執行緒與GC執行緒同時執行(不一定是並行,可能交替,但總體上是在同時執行的),不需要停頓使用者執行緒(其實在 CMS 中使用者執行緒還是需要停頓的,只是非常短,GC 執行緒在另一個 CPU 上執行);

並行收集:

指多個 GC 執行緒並行工作,但此時使用者執行緒是暫停的;

所以,Serial 是序列的,Parallel 收集器是並行的,而 CMS 收集器是併發的。

總結

今天瞭解了一下普通的垃圾收集器,並且詳細介紹了 CMS,其特性其實是基於普通的垃圾演算法,增加了預處理、預清除的過程,因此效率更加優越。當然它也有自己的缺點,更加消耗資源,因此在選用的時候需要結合實際場景。

有興趣的話可以訪問我的部落格或者關注我的公眾號、頭條號,說不定會有意外的驚喜。

https://death00.github.io/

相關推薦

GC 知識點補充——CMS

之前已經講過了不少有關 GC 的內容,今天準備將之前沒有細講的部分進行補充,首先要提到的就是垃圾收集器。 基礎的回收方式有三種:清除、壓縮、複製,衍生出來的垃圾收集器有: Serial 收集器 新生代收集器,使用停止複製演算法,使用一個執行緒進行 GC ,序列,其它工作執行緒暫停。 使用-XX:+UseSe

2017-5-15 winform項目總結(知識點補充

name inf tostring 總結 用法 傳值 draw ring rgs 1.groupBox 屬性重寫,增加邊框,事件paint    private void groupBox1_Paint(object sender, PaintEventArgs e

索引知識點補充

目的 exe row 訪問 分享 exp 反轉 下使用 比例 一、索引中包含like關鍵字 在索引列上使用like該列會不會使用到索引? 在聯合索引上前面索引字段使用like之後後面的列上會不會用到索引? 如果索引字段上使用 like ‘%xxx‘,這種

ffmpeg 知識點補充

ffmpeg 分數 表達方式提供一種可能解決avformat_find_stream_info耗時問題方案之前,先了解一些基本的ffmpeg的知識點先看代碼pFormatContext->streams[video_index]->time_base.den = 1200000;pFormatC

13.Django之數據庫models&orm連表操作補充以及其他知識點補充(二)

http 但是 int migrate .py app migration esp rfi 一.外鍵關聯。假如說,現在有兩張表,一張user表,這個表中存放了用戶賬戶信息,還有一張usertype表,這張表存放了用戶賬戶的類型。from django.db import

Flask-論壇開發-4-知識點補充

token day load() regex self 定義 文件類型 執行 rec 對Flask感興趣的,可以看下這個視頻教程:http://study.163.com/course/courseLearn.htm?courseId=1004091002 1. WTFor

Python全棧__叠代器、生成器、知識點補充、列表推導式,生成器表達式、如何系統科學的學習Python

ide swa XP iter count CA slow iterable 就是 1、叠代器   (1)可叠代對象 1 s1 = ‘123‘ 2 for i in s1: 3 print(i) 可叠代對象   示例結果: D:

HTML DOM知識點補充

nbsp data-* nodes first 子節點 remove class rip ttr DOM Console 控制臺對象提供了瀏覽器的debug的方法支持。 常用的:console.log()。 ??coffeescript中,這個方法不加括號。 DOM D

2018.08.23知識點補充簡單記錄

倒置 info 作業 nbsp 設計原則 文件 file spa 關於 一,file操作中seek方法的三種模式 以及 如何用 .seek(int,2)這種模式讀取文件最後一行 補充到了博客隨筆中的 文件操作 部分 二,函數默認參數的陷阱: 三,python的兩個

深淺拷貝 知識點補充

deep port pre 發現 元素 name style color () 深淺拷貝 lst1 = ["金毛獅王", "紫衫龍王", "白眉鷹王", "青翼蝠王"] lst2 = lst1 print(lst1) print(lst2) lst1.append("楊逍

set集合,深淺拷貝以及部分知識點補充

目錄:   1.基礎資料型別補充   2.set集合   3.深淺拷貝 一,基礎資料型別補充   字串的基本操作 li = ["李李嘉誠", "麻花藤", "⻩黃海海峰", "劉嘉玲"] s = "_".join(li) print(s) li = "⻩黃花⼤大閨⼥女女" s =

chapter10.2基礎知識點補充

__slots__   最簡單的hash演算法,取餘,便於理解模型   字典為了提高查詢效率,使用空間換時間   例項的屬性都需要一個空間,裡邊只放一兩個了浪費   解決數百萬個物件問題,字典就太多了 此時就可以用slots解決,只要定義了__slots__,物件的字典消失 __slots__中沒

GC知識點

一、判斷物件是否存活 1、引用計數法 2、可達性分析 就是通過一系列的稱為“GC Roots”的物件作為起始點,從這些節點開始向下搜尋,搜尋所走過的路徑稱為引用鏈(Reference Chain),當一個物件到GC Roots沒有任何引用鏈相連,則證明此物件是不可用的。 GC

3-5-2 知識點補充——mongoDB+Robo 3T安裝使用教程

安裝教程 首先準備工作: 需要的小夥伴可以在最下方點選連結下載相關程式 具體安裝步驟如下:  1、先安裝nodejs。需要下載node.js的這裡有穩定版node-v8.4.0-x64.msi  2、安裝mongodb 安裝在預設地址 如果可以直接開啟 直接

python學習打卡 day07 set集合,深淺拷⻉貝以及部分知識點補充

本節的主要內容: 基礎資料型別補充 set集合 深淺拷貝 主要內容: 一.基礎資料型別補充 字串: li = ["李嘉誠", "麻花藤", "⻩海峰", "劉嘉玲"] s = "_".join(li) print(s) # 李嘉誠_麻花藤_黃海峰_劉嘉玲 可以看出 join() 的作用是把列表中

我的Python成長之路--Day41-知識點補充(socketserver)

之前我們學了socket的使用,在我們建立socket物件的時候,不管是基於TCP還是UDP都有一點繁瑣,特別是TCP,可能有很多人記不住流程,那麼我們今天來給大家介紹一下socketserver Socketserver 1、什麼是socketserver: socke

JavaScript知識點補充

深拷貝 //遞迴方式 function deepCopy(source){ if(!source || typeof source !== 'object'){ throw ne

系統最常用的CMS GC mode——ParNew & CMS(Serial Old作為替補)(heap> 5g)

工作中 常用的 CMS  GC模式   refer to http://iamzhongyong.iteye.com/blog/1989829 如何讀懂GC日誌: 注: CMS GC下 會在特殊情況(jvm認為記憶體不夠了concurren

openstack--10--知識點補充

uid 比較 info open 技術 uuid 分享圖片 mage www 關於uuid和Fernet方式比較 提供令牌有四種方式[fernet|pkiz|pki|uuid]默認是uuid。 openstack--10--知識點補充