Java性能優化權威指南-讀書筆記(四)-JVM性能調優-延遲

延遲指服務器處理一個請求所花費的時間,單位通常是ms、s。html

本文主要講下降延遲能夠作的服務器端JVM優化。java

JVM延遲優化

新生代

新生代大小決定了應用平均延遲服務器

若是平均Minor GC持續時間大於應用程序平均延遲性要求,能夠適當減少新生代空間大小;多線程

若是Minor GC頻率大於應用程序平均延遲性要求,能夠適當增大新生代空間;併發

老年代

老年代大小決定了應用最差延遲性能

FullGC頻率大於應用程序最大FullGC頻率要求,能夠適當增大老年代空間大小;優化

FullGC持續時間大於應用程序最差延遲性要求,可使用CMS垃圾收集器;ui

CMS收集器調優

CMS主要特性

CMS爲老年代收集器,收集線程能與應用程序線程實現最大的並行度,下降了延遲。spa

CMS並不進行壓縮,因此老年代使用空閒列表分配內存,在必定程度上增長了新生代晉升老年代時,耗費的時間。線程

但一旦老年代溢出就會觸發Stop-The-World壓縮式垃圾收集。

因此,CMS的優化大概有下面幾點:

1. 避免用盡老年代空間;

2. 解決老年代碎片化問題,解決方法包括壓縮、MinorGC回收原則;

3. 下降初始標記階段和從新標記階段佔用的時間,由於這兩個階段應用程序線程會被阻塞;

Survivor空間調優

調整Survivor空間,是爲了讓其有足夠空間容納存活對象足夠長的時間,直到幾個週期後對象老化,解決上面的第1、二條問題。

Survivor空間的大小能夠經過下面這個參數調整:

-XX:SurvivorRatio=<ratio>

<ratio>必須大於0,-XX:SurvivorRatio=<ratio>表示單個Survivor和Eden的比率。

survivor空間大小  = –Xmn/(-XX:SurvivorRatio=<ratio> + 2)

 

監控晉升閾值

-XX:MaxTenuringThreshold=n     //設置最大晉升閾值

-XX:+PrintTenuringDistribution   //打印晉升的分佈或對象年齡分佈到GC日誌

以下面這個晉升日誌:

Desired survivor size 1114112 bytes, new threshold 1 (max 6)
- age   1:    2213864 bytes,    2213864 total

Desired survivor size 1114112 bytes是Survivor空間大小 * 目標存活率(能夠設定,默認50%)

new threshold 1 JVM內部計算出的晉升閾值 (max 6)設置的晉升閾值

age   1(對象年齡代)   2213864 bytes(這個年齡對象總大小),    2213864 total(全部年齡對象總大小)

Survivor目標存活率:指Minor GC後Survivor空間佔用比率,若是太大,下次Minor GC後存活的對象就有可能放不下

 

從這個日誌能夠看出,存活對象2213864bytes大於指望Survivor大小爲1124112bytes,因此對象年齡爲1時,就提高到了老年代。

解決這個問題的方法就是增大Survivor空間,存活對象大小 / 目標存活率 = Survivor空間大小,本例中大概4.5M,因此修改JVM參數爲:

-Xmx512m -Xms512m -Xmn50m -XX:SurvivorRatio=5

調整後的晉升日誌大概以下,這個已不是上面那個應用了,因此Survivor空間不同,能說明問題就行:

Desired survivor size 87359488 bytes, new threshold 15 (max 15)
- age   1:   20701528 bytes,   20701528 total
- age   2:    4924656 bytes,   25626184 total
- age   3:    3261000 bytes,   28887184 total
- age   4:    7941120 bytes,   36828304 total

調整Survivor空間的一個重要原則:

調整Survivor空間時,應保持Eden空間不變,不然會致使Minor GC頻率變小。

初始化CMS收集週期

CMS中發生的Stop-The-World壓縮式垃圾收集能夠在GC日誌中查找併發模式失效(concurrent mode failure)定位。

若是有這個問題,就須要調整CMS收集週期。

-XX:CMSInitiatingOccupancyFraction=<percent>    //設置CMS垃圾收集週期在老年代空間佔用達到多少是啓動

-XX:+UseCMSInitiatingOccupancyOnly                  //告知JVM老是使用 CMSInitiatingOccupancyFraction比率啓動CMS,不然只是在CMS第一次啓動時

原則:CMSInitiatingOccupancyFraction設置的比率至少是老年代活躍數據的1.5倍

若是老年代空間消耗的比較慢,能夠稍晚啓動CMS,即將CMSInitiatingOccupancyFraction設定的更大;

若是老年代空間消耗的很快,能夠將CMSInitiatingOccupancyFraction設定的更小,但不能低於活躍數據佔用的比率;

下降CMS從新標記階段佔用時間

-XX:ParallelGCThreads   //控制從新標記的線程數,建議將CMS的收集線程數設置的小於默認值,不然大量GC線程會影響應用性能

-XX:+CMSScavengeBeforeRemark  //在CMS進入從新標記階段先進行一次Minor GC,能夠減小引用老年代的新生代對象數量,下降從新標記階段的工做量

-XX:+ParallelRefProcEnabled    //使用多線程處理引用,不過在JDK6u25和6u26上有BUG

相關文章
相關標籤/搜索