垃圾收集器准则和提示
這些是我需要調整GC時通常會看到的一些準則和技巧。 主要由以下兩本書組成,而根據我的經驗卻很少:
- Java性能
- JBoss AS 5性能調優
希望它們對那里的其他人有用!
垃圾收集器
XX:+AggressiveOpts將HotSpot內部布爾變量設置為true以啟用其他性能優化
****************************************************** ******************************************************
由于大多數對象在其生命周期內最多只能被一個線程鎖定,因此啟用-XX:+ UseBiasedLocking可使該線程將鎖定偏向自身。 一旦有偏見,該線程便可以隨后鎖定和解鎖對象,而無需訴諸昂貴的原子指令
****************************************************** ******************************************************
要打印默認的人體工程學值:
java -XX:+PrintCommandLineFlags -version
****************************************************** ******************************************************
-XX:+PrintGCDetails打印更多且更有價值的垃圾收集信息。
以下示例顯示了通過-XX:+UseParallelGC或-XX:+UseParallelOldGC啟用的Java 6 Update 25吞吐量垃圾收集器的-XX:+PrintGCDetails輸出示例。 輸出分布在多行中,以便于閱讀。
[GC [PSYoungGen: 99952K->14688K(109312K)] 422212K->341136K(764672K), 0.0631991 secs] [Times: user=0.83 sys=0.00, real=0.06 secs]****************************************************** ******************************************************
包括日期和時間戳
-XX:+PrintGCTimeStamps
YYYY-MM-DD-T-HH-MM-SS.mmm-TZ
當-XX:+PrintGCDetails與-Xloggc:<filename>結合使用時,即使不指定-XX:+PrintGCTimeStamps ,輸出也會自動帶有時間戳作為前綴。
****************************************************** ******************************************************
[Full GC (System) [PSYoungGen: 99608K->0K(114688K)] [PSOldGen: 317110K->191711K(655360K)] 416718K->191711K(770048K) [PSPermGen: 15639K->15639K(22528K)], 0.0279619 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]系統意味著代碼中有一個System.gc()
****************************************************** ******************************************************
http://sysadminsjourney.com/2008/09/15/profile-gc-with-gchisto/
****************************************************** ******************************************************
VisualVM和VisualGC插件
如果遠程,則需要安裝jstatd守護程序
****************************************************** ****************************************************
分層服務器運行時是通過-server -XX:+TieredCompilationcommand行選項啟用的。
小費
如果您不知道最初選擇哪個運行時,請從服務器運行時開始。 如果無法滿足啟動時間或內存占用量要求,并且您正在使用Java 6 Update 25或更高版本,請嘗試分層服務器運行時。 如果您沒有運行Java 6 Update 25或更高版本,或者分層服務器運行時無法滿足啟動時間或內存占用量要求,請切換到客戶端運行時。
****************************************************** ****************************************************
32位或64位JVM
| 操作系統 | Java堆大小 | 32位或64位JVM |
| 視窗 | 小于1300 MB | 32位 |
| 視窗 | 介于1500 MB和32 GB之間[*] | 64位-d64 -XX:+ UseCompressedOops命令行選項 |
| 視窗 | 超過32 GB | 帶-d64命令行選項的64位 |
| 的Linux | 小于2 GB | 32位 |
| 的Linux | 2到32 GB之間[*] | 64位-d64 -XX:+ UseCompressedOops命令行選項 |
| 的Linux | 超過32 GB | 帶-d64命令行選項的64位 |
| Oracle Solaris | 小于3 GB | 32位 |
| Oracle Solaris | 介于3到32 GB之間[*] | 64位-d64 -XX:+ UseCompressedOops命令行選項 |
| Oracle Solaris | 超過32 GB | 帶-d64命令行選項的64位 |
[*]在具有-XX:+UseCompressedOops的64位HotSpot VM中,最佳性能約為最大Java堆大小大約26 GB或更小。
Java 6 Update 18以后的HotSpot VM版本默認基于最大Java堆大小自動啟用-XX:+UseCompressedOops 。
****************************************************** ****************************************************
從parallelOldDC開始:古老的收藏集是多線程的
吞吐量垃圾收集器由HotSpot VM命令行選項-XX:+UseParallelOldGC或-XX:+UseParallelGC 。 如果-XX:+UseParallelOldGC在您使用的HotSpot VM版本中不可用,請使用-XX:+UseParallelGC 。 兩者之間的區別在于-XX:+UseParallelOldGC啟用了多線程的年輕代垃圾收集器和多線程的舊代垃圾收集器,即次要垃圾收集和完整垃圾收集都是多線程的。 -XX:+UseParallelGC僅啟用多線程年輕代垃圾收集器。 與-XX:+UseParallelGC一起使用的舊式垃圾收集器是單線程的。 使用-XX:+UseParallelOldGC也會自動啟用-XX:+UseParallelGC 。 因此,如果要同時使用多線程年輕代垃圾收集器和多線程舊代垃圾收集器,則只需指定-XX:+UseParallelOldGC 。
****************************************************** ****************************************************
垃圾收集日志記錄:
-XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:<filename>
在將HotSpot VM調整為低延遲時,以下兩個命令行選項很有用,因為它們報告了由于VM安全點操作而導致應用程序被阻止的時間,以及應用程序在安全點操作之間執行了多長時間。
? -XX:+PrintGCApplicationStoppedTime
? -XX:+PrintGCApplicationConcurrentTime
選項-XX:+PrintSafepointStatistics可以幫助區分垃圾收集安全點和其他安全點。
-XX:+PrintGCApplicationConcurrentTime命令行選項可用于確定應用程序是否正在執行,以及在觀察到的響應時間超過了應用程序要求的某個感興趣的時間段內執行了多長時間。
****************************************************** ****************************************************
建議的GC日志記錄命令行選項
| GC命令行選項 | 最適用 |
| -XX:+ PrintGCTimeStamps -XX:+ PrintGC詳細信息 -Xloggc:<文件名> | 為所有應用程序啟用的最少的命令行選項集。 |
| -XX:PrintGCDateStamps | 在希望查看日歷日期和時間而不是指示自JVM啟動以來的秒數的時間戳時使用。 需要Java 6 Update 4或更高版本。 |
| -XX:+ PrintGCApplicationStoppedTime -XX:+ PrintGCApplicationConcurrentTime -XX:+ PrintSafepointStatistics | 在調整應用程序以降低響應時間/延遲時很有用,有助于區分VM安全點操作和其他來源引起的暫停事件。 |
XX:+PrintCommandLineFlags在HotSpot VM初始化時將選定的初始堆大小和最大堆大小打印為-XX:InitialHeapSize=<n>
-XX:+PrintTenuringDistribution
****************************************************** ****************************************************** ************************
-XX:MaxHeapSize=<m> ,其中<n>是初始Java堆大小(以字節為單位), <m>是最大Java堆大小(以字節為單位)
****************************************************** ****************************************************** ************************
| 空間 | 命令行選項 | 占用率 |
| Java堆 | -Xms和-Xmx | 完全垃圾收集后,老一代空間占用率為3到4倍 |
| 永久世代 | -XX:PermSize -XX:MaxPermSize | 完全垃圾收集后,永久生成空間占用率為1.2x到1.5x |
| 年輕一代 | -Xmn | 完全垃圾收集后,老一代空間占用率為1到1.5倍 |
| 老一代 | 從Java總堆大小減去年輕代大小中隱含 | 完全垃圾收集后,老一代空間占用率為2到3倍 |
****************************************************** ****************************************************** ************************
年輕空間
-XX:NewSize=<n>[g|m|k]
-XX:MaxNewSize=<n>[g|m|k]
-Xmn<n>[g|m|k]
-Xmn可以方便地確定年輕一代空間的初始大小和最大大小
如果(-Xmx != -Xms) && -Xmn存在
Java堆大小的增長或收縮不會調整年輕代空間的大小。
隨Java堆大小的任何增長或收縮,年輕代空間的大小將保持不變。 因此,僅當-Xms和-Xmx設置為相同的值時, -Xmn應使用-Xmn 。
****************************************************** ****************************************************** ************************
燙發大小
-XX:PermSize=<n>[g|m|k]
-XX:MaxPermSize=<n>[g|m|k]
注重性能的Java應用程序應將初始和最大永久生成大小( -XX:PermSize和-XX:MaxPermSize )的大小都設置為相同的值,因為增加或縮小永久生成空間需要完整的垃圾回收。
****************************************************** ****************************************************** ************************
-XX:-ScavengeBeforeFullGC將在完整垃圾收集上禁用年輕一代空間垃圾收集。
****************************************************** ****************************************************** ************************
2010-11-25T18:51:03.895-0600: [Full GC [PSYoungGen: 279700K->267300K(358400K)][ParOldGen: 685165K->685165K(685170K)] 964865K->964865K(1043570K) [PSPermGen: 32390K->32390K(65536K)], 0.2499342 secs] [Times: user=0.08 sys=0.00, real=0.05 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space2010-11-25T18:26:37.755-0600: [Full GC [PSYoungGen: 0K->0K(141632K)] [ParOldGen: 132538K->132538K(350208K)] 32538K->32538K(491840K)[PSPermGen: 65536K->65536K(65536K)], 0.2430136 secs] [Times: user=0.37 sys=0.00, real=0.24 secs] java.lang.OutOfMemoryError: PermGen space如果您在垃圾回收日志中觀察到OutOfMemoryError ,請嘗試將Java堆大小增加到JVM可用物理內存的80%到90%。
例如,對于舊世代空間OutOfMemoryErrors,增加-Xmsand -Xmx ;對于永久世代OutOfMemoryErrors,增加-XX:PermSize和-XX:MaxPermSize 。
下一步是計算應用程序的實時數據大小。
****************************************************** ****************************************************** ************************
計算實時數據大小
除了實時數據大小外,處于穩態的完整垃圾收集還提供了由于完整垃圾收集而導致的最壞情況下的延遲。
您可以使用實時數據(應用程序繁忙時間內的perm空間+滿GC后的舊空間)來計算初始堆大小:
通常,初始和最大Java堆大小命令行選項-Xms和-Xmx的值應設置為舊空間的實時數據大小的三到四倍。
完全垃圾回收后的舊一代空間占用為295111K,或大約295 MB。因此,實時數據大小為大約295 MB
因此,為此應用程序指定的建議初始Java堆大小和最大Java堆大小應為885到1180兆字節之間的值,即-Xms1180m -Xmx1180m是實時數據大小的四倍。
同樣作為一般規則,初始和最大永久世代大小-XX:PermSize和-XX:MaxPermSize應該比永久世代空間的活動數據大小大1.2倍至1.5倍。
在上圖所示的示例完整垃圾收集中,完整垃圾收集后的永久生成空間占用為32390K,約32兆字節。 因此,為此應用程序指定的建議的初始和最大永久生成空間大小應在38兆字節和48兆字節之間,即-XX:PermSize = 48m -XX:MaxPermSize = 48m,是永久生成實時數據大小的1.5倍。
作為附加的一般規則,年輕代空間應為舊代空間活動數據大小的1到1.5倍。
結果,建議的年輕代大小應在295到442兆字節之間。 在上圖中,年輕一代的空間大小為358400K,約358兆字節。 358兆字節在建議的大小以內。
如果初始和最大Java堆大小是實時數據大小的3倍至4倍,而年輕代空間是實時數據大小的1倍至1.5倍,則舊代空間的大小應在實時數據大小的2倍至3倍之間。
基于上圖中的垃圾收集數據,應用這些常規大小調整規則的組合Java命令行為
$ java -Xms1180m -Xmx1180m -Xmn295m
-XX:PermSize=48m -XX:MaxPermSize=48m
| 空間 | 命令行選項 | 占用率 |
| Java堆 | -Xms和-Xmx | 完全垃圾收集后,老一代空間占用率為3到4倍 |
| 永久世代 | -XX:PermSize -XX:MaxPermSize | 完全垃圾收集后,永久生成空間占用率為1.2x到1.5x |
| 年輕一代 | -Xmn | 完全垃圾收集后,老一代空間占用率為1到1.5倍 |
| 老一代 | 從Java總堆大小減去年輕代大小中隱含 | 完全垃圾收集后,老一代空間占用率為2到3倍 |
****************************************************** ****************************************************** ************************
音調延遲/響應能力
評估垃圾收集器對延遲的影響涉及以下活動:
- 測量次要垃圾收集時間
- 測量次要垃圾收集頻率
- 測量最壞情況下的完整垃圾收集持續時間
- 測量最壞情況下的全部垃圾收集頻率
調整年輕代的大小
從parallelGC到并發的-XX:+UseConcMarkSweepGC
如果最壞的情況下,完整垃圾收集持續時間或頻率收集頻率太高
隨著年輕一代人數的變化,要記住的其他一般準則是
- 老一代的空間大小應不小于實時數據大小的1.5倍。 有關實時數據大小的定義和其他舊版本調整大小的準則,請參見上一節“ 確定內存占用空間 ”。
- 年輕代的空間大小至少應為Java堆大小的10%,該值指定為-Xmx和-Xms。 很小的年輕一代可能適得其反。 它導致頻繁的次要垃圾收集。
- 增加Java堆大小時,請注意不要超過JVM可用的物理內存量。 Java堆大小消耗的內存足以導致基礎系統交換到虛擬內存,從而導致垃圾收集器和應用程序性能下降。
調整舊一代的大小
這項任務的目的是評估由完整垃圾收集引起的最壞情況下的暫停時間以及完整垃圾收集的頻率。
如果您僅觀察完整的垃圾收集
在修改舊世代空間的大小時,舊世代大小可能會與年輕世代大小失去平衡,并導致應用程序僅經歷完整的垃圾回收。 通常,這發生在舊的一代空間不夠大而無法容納所有從年輕一代空間提升的對象時,即使在進行完整的垃圾回收之后。
老式空間不夠大的關鍵指標是,老式空間中的回收空間很小(ParOldGen標簽右側的值),并且在每個完整空間之后,大部分年輕空間仍然被占用。垃圾收集。 當舊一代中沒有足夠的空間來處理年輕一代的提升對象時,如先前輸出中所觀察到的,對象將“備份”到年輕一代空間中。
如果由于完整的垃圾收集持續時間太長而無法滿足應用程序最壞情況下的延遲要求,那么您應該切換到使用并發垃圾收集器 。
使用HotSpot命令行選項啟用并發垃圾收集器:
-XX:+UseConcMarkSweepGC
****************************************************** ****************************************************** ************************
避免幸存者空間溢出是通過調整幸存者空間的大小來實現的,以使幸存者空間足夠大,可以將幸存的對象放置足夠長的時間,以便在一段時間內老化。 有效的老化只會將壽命長的物體提升到舊的空間。
小費
老化是將對象保留在年輕一代中直至無法再訪問的一種方法,以便為壽命更長的對象保留老一代空間。
使用HotSpot命令行選項確定幸存者空間的大小:
-XX:SurvivorRatio=<ratio>
<ratio>的值必須大于0。- -XX:SurvivorRatio=<ratio>表示每個幸存者空間與eden空間之間的空間比率。 以下公式可用于確定幸存者空間大小:
幸存者空間大小= -Xmn<value>/(-XX:SurvivorRatio=<ratio> + 2)
指定為比率的值越大,幸存者空間大小越小。
權屬閾值解釋
小費
在年輕一代中有效的對象老化可以防止它們過早地提升到老一代空間,從而降低了老一代的占用率。 這減少了CMS垃圾回收周期必須執行的頻率,還減少了碎片的可能性。
還有一個HotSpot虛擬機命令行選項, -XX:MaxTenuringThreshold=<n>可用于詢問HotSpot虛擬機僅一個對象的年齡之后,以促進對象的老一代空間超出的值<n>
對于Java 5 Update 6和更高版本,最大使用期限閾值可以設置為0–15,對于Java 5 Update 5和更低版本,可以設置為0–31。
不建議將最大使用期限閾值設置為0。這將導致在分配對象后,在下一個次要垃圾回收中將對象立即從年輕代升級到老一代。 這將非常Swift地擴展舊一代的空間,并導致頻繁的完整垃圾收集。
還不建議將最大使用期限閾值設置為大于可能的最大值。 這將導致對象保留在幸存者空間中,直到幸存者空間溢出為止。 如果它們溢出,則對象將被無差別地提升為老一代,也就是說,它們不會根據其年齡來提升。 結果,可以在壽命較長的對象之前提升壽命較短的對象,這防止了有效的對象老化。
小費
通常,觀察新的占位閾值始終小于最大占位閾值,或觀察所需的幸存者大小小于幸存總字節數(對象年齡的最后一行和最右邊的列的值)表明幸存者空間太小。
****************************************************** ****************************************************** ************************
啟動CMS收集周期
停止世界壓縮垃圾收集是最壞情況下垃圾收集導致的延遲
CMS周期的啟動基于舊空間的占用
如果觀察到世界各地的壓縮垃圾收集,則可以調整CMS周期何時開始。 并發模式故障會在垃圾回收輸出中標識CMS中的“停止世界”壓縮垃圾回收。 以下是一個示例:
174.445: [GC 174.446: [ParNew: 66408K->66408K(66416K), 0.0000618 secs]174.446: [CMS (concurrent mode failure): 161928K->162118K(175104K), 4.0975124 secs] 228336K->162118K(241520K)如果您在垃圾回收輸出中觀察到并發模式故障,則可以使用命令行選項指示HotSpot VM提前啟動CMS周期的開始:
-XX:CMSInitiatingOccupancyFraction=<percent>
指定的值是CMS垃圾回收周期應開始的舊占用率的百分比。 例如,如果您希望CMS周期以舊的65%的空間占用率開始,則可以設置-XX:CMSInitiatingOccupancyFraction=65 。 第二個HotSpot命令行選項應與– XX:CMSInitiatingOccupancyFraction=<percent>結合使用
-XX:+UseCMSInitiatingOccupancyOnly
-Xmx1536m -Xms1536m -Xmn512m
-XX:CMSInitiatingOccupancyFraction = 51
-XX:+僅使用CMSInitiatingOccupancy
顯式垃圾回收
如果觀察到完整的垃圾回收,這些回收是通過顯式調用System.gc() ,那么在使用并發垃圾回收器時有兩種處理方法:
盡管在垃圾收集輸出中報告了CMS Perm標簽,但默認情況下,HotSpot VM不會通過CMS垃圾收集永久生成空間。 要啟用CMS永久生成垃圾收集,您必須指定以下HotSpot VM命令行選項:
-XX:+CMSClassUnloadingEnabled
如果使用的是Java 6 Update 3或更早版本,則除了-XX:+ CMSClassUnloadingEnabled外,還必須指定以下命令行選項: -XX:+CMSPermGenSweepingEnabled
CMS暫停時間調整
備注階段中使用的線程數可以由以下HotSpot VM命令行選項控制:
-XX:ParallelGCThreads=<n>
在某些情況下,可以通過指定以下內容來縮短備注階段的持續時間:
-XX:+CMSScavengeBeforeRemark
此命令行選項強制HotSpot VM在CMS注釋之前執行次要垃圾回收。 在備注之前進行次要垃圾回收,可以通過減少舊一代空間中可能到達的舊一代空間中的對象數量,來最大程度地減少備注階段的工作量。
如果應用程序中有大量要處理的引用或可終結對象,則指定以下HotSpot VM命令行選項可以幫助減少垃圾回收時間:
-XX:+ParallelRefProcEnabled
最新和最優化
當新的性能優化集成到HotSpot VM中時,通常會在命令行選項-XX:+AggressiveOpts下引入它們。
如果應用程序涉眾正在尋求其他性能并愿意接受與啟用最新優化相關的其他小風險,則應考慮使用-XX:+AggressiveOpts命令行選項。
轉義分析
轉義分析是一種評估Java對象范圍的技術。 特別是,如果某個執行線程分配的Java對象可以被其他線程看到,則該對象“轉義”。 如果Java對象無法轉義,則可以應用其他優化技術。 因此,優化技術稱為逃逸分析。
使用以下命令行選項啟用HotSpot VM中的轉義分析優化:
-XX:+DoEscapeAnalysis
Linux上的大頁面
-XX:+UseLargePages
翻譯自: https://www.javacodegeeks.com/2013/12/garbage-collector-guidelines-and-tips.html
總結
以上是生活随笔為你收集整理的垃圾收集器准则和提示的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓优势与劣势(安卓优势)
- 下一篇: 使用Hazelcast发布和订阅