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:
- 首先 JVM 根據
-XX:CMSInitiatingOccupancyFraction
、-XX:+UseCMSInitiatingOccupancyOnly
來決定什麼時間開始垃圾收集。 - 如果設定了
-XX:+UseCMSInitiatingOccupancyOnly
,那麼只有當老年代佔用確實達到了-XX:CMSInitiatingOccupancyFraction
引數所設定的比例時才會觸發 CMS GC。 - 如果沒有設定
-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)
此階段暫停應用執行緒,停頓時間比並發標記小得多,但比初始標記稍長,因為會對所有物件進行重新掃描並標記。
此階段會列印以下日誌:
- YG occupancy:964861K(2403008K),指執行時年輕代的情況。
- CMS remark:961330K(1572864K),指執行時老年代的情況。
- 此外,還打印出了弱引用處理、類解除安裝等過程的耗時。
併發清除(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--知識點補充