Gc調優的目標:1.下降停頓時間 2.提升吞吐量 3.避免full-gc算法
調優可使用的手段:
1.各個內存區的大小調整:堆,年輕代,老年代,方法區等等
2.減小短暫對象的存活時間,提升長期對象的複用率(對象池,cache,永久區等等),減小沒必要要的垃圾的生產。
3.調整對象的晉升:晉升閾值,survivor的目標存活值,大小等
3.併發控制:併發,並行的gc線程數
3.提早開始併發週期
4.G1能夠調整mix-清理週期的目標值,儘快結束mix-清理週期。併發
1. 下降停頓時間+保存合理的吞吐量:
年輕代:調小年輕代的大小+減小垃圾的產生速度+減小垃圾的存活時間。即,不必產生的對象就不用建立了,一次性的對象要讓它死的快,不容易死的對象要增長複用率。這還有利於減小對象的晉升,減小老年代的壓力。
老年代:a.一樣能夠調小老年代的大小。可是也會帶來吞吐量的問題。若是物理內存夠大的話,可使用G1。一樣能夠減小對象的存活時間,這樣能夠在老年代的gc中,儘快的清理掉多數的垃圾,能夠防止晉升失敗和併發失敗。
b.加快老年代的gc速度。能夠調整併發值,也就是gc的線程數。可是要考慮機器的cpu資源和應用的cpu使用狀況,要儘可能的提升cpu的使用率,可是不要形成搶佔CPU,由於這樣會使吞吐量降低。
2. 提升吞吐量:
1. 在gc停頓和頻率直接的權衡
2. 線程和cpu資源的考量
3. Gc算法 並行 vs 併發
3. 避免full-gc:
Full-gc的致使有幾個緣由:1.超大對象 2.併發失敗 3.內存碎片 4.永久代滿了
併發失敗的形成緣由是對象的晉升速度超過了老年代的清理速度。因此解決方案就是讓這場追趕比賽的懸殊更大一些。
1. 增長堆的大小
2. 下降年輕代的垃圾晉升速度: 對象的快速死亡,減小沒必要要的對象建立,survivor區調整(目標:充分利用survivor區,保證對象是到達必定年齡才發生晉升而不是 由於溢出而晉升),調大堆區
3. 加快併發週期的速度:併發控制
4. 提早併發週期:提早併發週期(這會致使併發週期的頻率增長,因此須要進行權衡),G1調整清理週期目標(清理週期太長,會致使併發週期時間太長,若是清理效率通常,會致使併發失敗。清理週期過短,可能會致使併發週期太頻繁,清理不夠完全,也有可能致使併發失敗,因此也須要進行權衡)
5. 提升老年代收集效率:減小對象生命週期
4. Remark階段的耗時優化:
「-XX:+PrintReferenceGC」參數,細化GC日誌中對系統內的軟引用、弱引用、虛引用的回收耗時。加上後發現,發現回收這些引用的耗時+類卸載的耗時成爲了整個CMS reamrk階段的瓶頸。因爲JDK8在Linux環境會默認開啓CMSClassUnloadingEnabled,這會使得CMS在CMS-remark階段嘗試進行類的卸載,然而經過cat能夠得知Metaspace空間穩定,無需每次fullgc都去主動卸載,故須要顯示關閉CMSClassUnloadingEnabled
性能
survivor區的調優:
目標: 1. 最基本的目標是保證對象是由於達到晉升閾值纔到達老年代,而不是由於溢出而到達老年代 2. 在目標1的基礎上,儘量的加大對象的晉升閾值,這樣能夠減輕老年代的壓力,固然也要考慮這樣給年輕代形成的壓力。最好不要爲了這個目標而把老年代調小,這樣會使full-gc的風險加大
方法:1. 晉升閾值的設置:-XX:MaxTenuringThreshold(最大晉升閾值) -XX:InitialTenuringThreshold=N (初始晉升閾值) ,有時爲了不溢出致使的晉升,不得已把晉升閾值調小
2. 設置survivor區的目標利用率(YGC後,survivor的佔用率) -XX:TargetSurvivorRatio 默認是50,通常這也是合適的
3. 減小對象的存活時間
4.調整堆的大小
思路:
1. -XX:+PrintTenuringDistribution 使用這個參數,gc日誌會打印各個年齡的對象的大小,再經過survivor的大小,咱們就能夠推斷是否會發生溢出了,也能夠根據survivor的大小設置合適的晉升閾值和目標值
2. 不可把survivor增長過大,由於會對象是直接在eden上分配的,若是eden減小,會帶來更多的性能問題。也不可過多減小老年代的大小,這樣會致使full-gc風險加大。最好的方法是增長堆的大小,調小survivor的利於率目標值。這樣eden和老年代都大概維持原有的大小,survivor區會加大。優化
TLAB: TLAB位於Eden區,是線程的進行快速分配內存是區域。由於它是thread local的,不像TLAB外的區域須要進行同步操做,因此比較快。當一個線程的tlab用盡的時候,有倆種動做:1. 直接在tlab外進行分配對象,這個線程後續的分配還會嘗試往這個tlab上進行分配。 2. 放棄這個tlab,在eden區從新分配一塊新的tlab。老的tlab會隨着ygc進行垃圾回收,可是老的tlab上的剩餘空間會被浪費。 操做這倆個動做的選擇是-XX:TLABWasteTargetPercent=N -XX:TLABWasteIncrement=N -XX:TLABSize=N
這些參數。它的大小默認是動態計算的。每次在tlab外分配完成後,都會使TLABWasteTargetPercent的值變大。
Tlab的大小默認由三個因素控制:應用程序的線程數、Eden 空間的大小以及線程的分配率 使用 -XX:-UseTLAB 能夠關閉tlabspa
大對象: 當一個大對象沒法在年輕代放得下時,就回直接進入老年代。 在G1中,若是大對象大於一個分區的大小,就會被放到老年代,並且在老年代中須要連續的分區來進行存放。若是沒有連續的分區,就會觸發併發週期,若是還不行,就會進行full-gc。因此大對象的影響是很大的。線程
G1調優:
G1 垃圾收集器調優的主要目標是避免發生併發模式失敗或者疏散失敗
• 經過增長總的堆空間大小或者調整老年代、新生代之間的比例來增長老年代空間的 大小。
• 增長後臺線程的數目(假設咱們有足夠的CPU資源運行這些線程)。
• 以更高的頻率進行G1的後臺垃圾收集活動。
• 在混合式垃圾回收週期中完成更多的垃圾收集工做。
調優方法:
1. 使用 -XX:MaxGCPauseMillis=N 可是若是太小的話,會致使年輕代和老年代都變小,從而致使gc頻繁,full-gc風險變大。
2. 增長後臺併發數 ParallelGCThreads ConcGCThreads
3. 調整併發週期頻率,儘早開始清理:-XX:InitiatingHeapOccupancyPercent=N G1是根據整個堆區,CMS是根據老年代的大小佔用 太大會致使full-gc風險變高,過小會致使gc太頻繁
4. 調整混合清理週期:併發週期以後、老年代的標記分區回收完成以前,G1 收集器沒法啓動新的併發週期。所以,讓 G1 收集器更早啓動標記週期的另外一個方法是在混合式垃圾回收週期中儘可能處理更 多的分區(如此一來最終的混合式 GC 週期就變少了,可是單次清理週期的停頓時間呼會變長):
混合式垃圾收集要處理的工做量取決於三個因素。
第一個因素是有多少分區被發現大部分 是垃圾對象。目前沒有標誌可以直接調節這個因素:混合式垃圾收集中,若是分區的垃圾 佔用比達到 35%,這個分區就被標記爲能夠進行垃圾回收。(這個因素在未來的某個時刻 可能也能調整,在開源的實驗版本中已經有名爲 -XX:G1MixedGCLiveThresholdPercent=N 的 參數能夠對其進行調整)。 第二個因素是 G1 垃圾收集回收分區時的最大混合式 GC 週期數,經過參數 -XX:G1MixedGCCountTarget=N 能夠進行調節。這個參數的默認值爲 8;減小該參數值能夠幫 助解決晉升失敗的問題(代價是混合式 GC 週期的停頓時間會更長)。 另外一方面,若是混合式 GC 的停頓時間過長,能夠增大這個參數的值,減小每次混合式 GC 週期的工做量。不過調整以前咱們須要確保增大值以後不會對下一次 G1 併發週期帶來 太大的延遲,不然可能會致使併發模式失敗。 最後,第三個影響因素是 GC 停頓可忍受的最大時長(經過 MaxGCPauseMillis 參數設定)。 MaxGCPauseMillis 標誌設定的混合式週期時長是向上規整的,若是實際停頓時間在停頓最大時長之內,G1 收集器可以收集超過八分之一標記的老年代分區(或者其餘設定的值)。 增大 MaxGCPauseMillis 能在每次混合式 GC 中收集更多的老年代分區,而這反過來又能幫 助 G1 收集器在更早的時候啓動併發週期。日誌
CMS調優:
CMS和G1的不一樣是,它的清理算法是標記清理,因此最後的清理是併發的,不會形成stw,因此不須要考慮g1中混合清理階段的一些問題。
CMS的調優目標也是避免併發失敗:
作法:
1.想辦法增大老年代空間,要麼只移動部分的新生代對象到老年代,要麼增長更多的堆 空間。 2.以更高的頻率運行後臺回收線程。 -XX:CMSInitiatingOccupancyFraction=N 和 -XX:+UseCMSInitiatingOccupancyOnly CMSInitiatingOccupancyFraction值的肯定,能夠先找到一個併發失敗的日誌,而後查看此次併發週期開始時,老年代的佔用比。 XX:+UseCMSInitiatingOccupancyOnly若是不指定, 只是用設定的回收閾值CMSInitiatingOccupancyFraction,則JVM僅在第一次使用設定值,後續則自動調整會致使上面的那個參數不起做用。
3.使用更多的後臺回收線程。對象