<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【JVM性能優(yōu)化】面向CMS垃圾回收器的性能優(yōu)化方案

          共 3948字,需瀏覽 8分鐘

           ·

          2021-06-23 08:36

          前提概要

          如果沒有冬天,春天不會如此悅?cè)耍蝗绻麤]有偶爾的不幸,幸運不會如此受人歡迎

          CMS垃圾回收的6個重要階段

          1. initial-mark 初始標(biāo)記(CMS的第一個STW階段),標(biāo)記GC Root直接引用的對象,GC Root直接引用的對象不多,所以很快。

          2. concurrent-mark并發(fā)標(biāo)記階段,由第一階段標(biāo)記過的對象出發(fā),所有可達的對象都在本階段標(biāo)記

          3. concurrent-preclean 并發(fā)預(yù)清理階段,也是一個并發(fā)執(zhí)行的階段。在本階段,會查找前一階段執(zhí)行過程中,[從新生代晉升或新分配或被更新的對象]。通過并發(fā)地重新掃描這些對象,預(yù)清理階段可以減少下一個stop-the-world 重新標(biāo)記階段的工作量

          4. concurrent-abortable-preclean并發(fā)可中止的預(yù)清理階段。這個階段其實跟上一個階段做的東西一樣,也是為了減少下一個STW重新標(biāo)記階段的工作量。增加這一階段是為了讓我們可以控制這個階段的結(jié)束時機,比如掃描多長時間(默認(rèn)5秒)或者Eden區(qū)使用占比達到期望比例(默認(rèn)50%)就結(jié)束本階段

          5. remark重標(biāo)記階段(CMS的第二個STW階段),暫停所有用戶線程,從GC Root開始重新掃描整堆,標(biāo)記存活的對象。需要注意的是,雖然CMS只回收老年代的垃圾對象,但是這個階段依然需要掃描新生代,因為很多GC Root都在新生代,而這些GC Root指向的對象又在老年代,這稱為“跨代引用”

          6. concurrent-sweep ,并發(fā)清理

          分析

          分析其GC日志,發(fā)現(xiàn)GC發(fā)生在CMS的收集階段

          • 箭頭1 顯示abortable-preclean階段耗時4.04秒

          • 箭頭2 顯示的是remark階段,耗時0.11秒

          • 雖然abortable-preclean階段是concurrent的,不會暫停其他的用戶線程。就算不優(yōu)化,可能影響也不大。

          調(diào)優(yōu)之前先看下該應(yīng)用的GC統(tǒng)計數(shù)據(jù),包括GC次數(shù),耗時:

          統(tǒng)計期間內(nèi)(18天)發(fā)生CMS GC 69次,其中abortable preclean階段平均耗時2.45秒,final remark階段平均112ms,最大耗時170ms。

          優(yōu)化目標(biāo)

          降低abortable preclean時間,而且不增加final remark的時間(因為remark是STW的)。

          JVM參數(shù)調(diào)優(yōu)

          第一次調(diào)優(yōu)

          先嘗試調(diào)低abortable preclean階段的時間,看看效果。

          有兩個參數(shù)可以控制這個階段何時結(jié)束:

          -XX:CMSMaxAbortablePrecleanTime=5000
          復(fù)制代碼

          默認(rèn)值5s,代表該階段最大的持續(xù)時間

          -XX:CMSScheduleRemarkEdenPenetration=50
          復(fù)制代碼

          默認(rèn)值50%,代表Eden區(qū)使用比例超過50%就結(jié)束該階段進入remark

          調(diào)整為最大持續(xù)時間為1s,Eden區(qū)使用占比10%,如下:

          -XX:CMSMaxAbortablePrecleanTime=1000

          -XX:CMSScheduleRemarkEdenPenetration=10
          復(fù)制代碼

          為什么調(diào)整成這樣兩個值:首先每次CMS都發(fā)生在老年代使用占比達到80%時,因為這是由下面兩個參數(shù)決定的

          -XX:CMSInitiatingOccupancyFraction=80
          -XX:+UseCMSInitiatingOccupancyOnly
          復(fù)制代碼

          這兩個設(shè)置一般配合使用,一般用于『降低CMS GC頻率或者增加頻率、減少GC時長』的需求

          • -XX:CMSInitiatingOccupancyFraction=80 是指設(shè)定CMS在對內(nèi)存占用率達到80%的時候開始GC(因為CMS會有浮動垃圾,所以一般都較早啟動GC);

          • -XX:+UseCMSInitiatingOccupancyOnly標(biāo)志來命令JVM不基于運行時收集的數(shù)據(jù)來啟動CMS垃圾收集周期

          當(dāng)該標(biāo)志被開啟時,JVM通過CMSInitiatingOccupancyFraction的值進行每一次CMS收集,而不僅僅是第一次。(否則后續(xù)會動態(tài)控制回收閾值)

          (慎用) 因此,只有當(dāng)我們充足的理由(比如測試)并且對應(yīng)用程序產(chǎn)生的對象的生命周期有深刻的認(rèn)知時,才應(yīng)該使用該標(biāo)志。

          老年代的增長是由于部分對象在Minor GC后仍然存活,被晉升到老年代,導(dǎo)致老年代使用占比增長的,也就是在每次CMS GC發(fā)生之前剛剛發(fā)生過一次Minor GC所以在那一刻新生代的使用占比是很低的

          那么我們預(yù)計這個時候盡快結(jié)束abortable preclean階段,在remark時就不需要掃描太多的Eden區(qū)對象,remark STW的時間也就不會太長

          第一次調(diào)整參數(shù)

          在統(tǒng)計期間(17小時左右)內(nèi),發(fā)生過2次CMS GC。Abortable Preclean 平均耗時835ms,這是預(yù)期內(nèi)的。但是Final Remark 平均耗時495ms(調(diào)整前是112ms),其中一次是80ms,另一次是910ms!將近1秒鐘!Remark是STW的!對于要求低延時的應(yīng)用來說這是無法接受的!

          [YG occupancy: 181274 K (1887488 K)] - 年輕代當(dāng)前占用情況和總?cè)萘?/p>

          耗時80ms的這次remark發(fā)生時(早上9點,非高峰時段),新生代(YG)占用181.274M。

          remark耗時910ms的那次GC日志

          [YG occupancy: 773427 K (1887488 K)]

          耗時910ms的這次remark發(fā)生時(晚上10點左右,高峰時段),新生代(YG)占用773.427M。因為這個時候高峰期,新生代的占用量上升的非常快,幾乎同樣的時間內(nèi),非高峰時段僅上升到181M,但是高峰時段就上升到773M。

          • 如果abortale preclean階段時間太短,隨后在remark時,新生代占用越大,則remark持續(xù)的時間(STW)越長

          • 不縮短abortale preclean耗時會出現(xiàn)過程gc;縮短的話,remark階段又會變長,而且是STW,更不能接受。

          對于這種情況,CMS提供了CMSScavengeBeforeRemark參數(shù),嘗試在remark階段之前進行一次Minor GC,以降低新生代的占用

          第二次調(diào)優(yōu)

          增加 -XX:+CMSScavengeBeforeRemark 不是沒有代價的,因為這會增加一次Minor GC停頓。所以這個方案好或者不好的判斷標(biāo)準(zhǔn)就是:增加CMSScavengeBeforeRemark參數(shù)之后的minor GC停頓時間 + remark 停頓時間如果比增加之前的remark GC停頓時間要小,這才是好的方案。

          -XX:+CMSScavengeBeforeRemark:在CMS GC前啟動一次ygc,目的在于減少old gen對ygc gen的引用,降低remark時的開銷-----一般CMS的GC耗時 80%都在remark階段

          第二次調(diào)整的結(jié)果

          在統(tǒng)計期間(20小時左右)內(nèi),發(fā)生3次CMS GC。Abortable preclean 平均耗時693ms。Final remark平均耗時50ms,最大耗時60ms。Final remark的時間比調(diào)優(yōu)前的平均時間(112ms)更低

          3次CMS GC remark前的Minor GC日志分析

          第1次是非高峰時段的表現(xiàn),Minor GC 耗時 0.01s + remark耗時 0.06s = 0.07s = 70ms,如下第2次是高峰時段,Minor GC 耗時 0.01s + remark耗時 0.05s = 0.06s = 60ms,如下第3次是非高峰時段,Minor GC 耗時 0.00s + remark耗時 0.04s = 0.04s = 40ms,如下

          所以,3次Minor GC + remark耗時的平均耗時 < 60ms,這比第一次調(diào)優(yōu)時remark平均耗時495ms好得多了

          總結(jié)

          解決abortable preclean 時間過長的方案可以歸結(jié)為兩步:

          縮短abortable preclean 時長,通過調(diào)整這兩個參數(shù):

          -XX:CMSMaxAbortablePrecleanTime=xxx

          -XX:CMSScheduleRemarkEdenPenetration=xxx
          復(fù)制代碼
          • 調(diào)整為多少的一個判斷標(biāo)準(zhǔn)是:abortable preclean階段結(jié)束時,新生代的空間占用不能大于某個參考值。在前面第一次調(diào)優(yōu)后,新生代(YG)占用181.274M,remark耗時80ms;新生代(YG)占用773.427M時,remark耗時910ms。所以這個參考值可以是300M。

          • 而如果新生代增長過快,像這次調(diào)優(yōu)應(yīng)用2秒內(nèi)就能用光2G新生代堆空間的,就只能通過CMSScavengeBeforeRemark做一次Minor GC了

          增加CMSScavengeBeforeRemark參數(shù)開啟remark前進行Minor GC的嘗試

          雖然官方說明這個增加這個參數(shù)是嘗試進行Minor GC,不一定會進行。但實際使用起來,幾乎每次remark前都會Minor GC。


          作者:李浩宇A(yù)lex
          鏈接:https://juejin.cn/post/6975125806305509389
          來源:掘金
          著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。



          瀏覽 88
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  学生妹毛片视频 | 天堂国产 | 亚洲性爱小说 | 韩国三级毛片 | wwwx欧美|