首頁>技術>

背景

在公司內部技術群裡,經常有人時不時的問到服務某次GC時間突然很高,有什麼辦法排查。基本上每次都會有人懷疑會不會Swap導致的,先看看Swap,如果真的使用了Swap區域,基本上就會讓Swap區域背鍋了。

案例案例一:CMS GC時間飆升

有次群裡有人給出一個case:CMS GC時間飆升,主要是remark階段的處理時間太長,給出的日誌如下:

群裡有人使用到了Swap區域。而對CMS GC如果有了解的話,想問的肯定是是不是加了“ -XX:+CMSScavengeBeforeRemark ”這個引數。在明確告知有這個引數。但是我在這個remark階段並沒有看到young gc,提問者就又截了一個全一點的日誌,如下:

感覺日誌在remark之前並沒有進行young gc,正常的加入“ -XX:+CMSScavengeBeforeRemark ”引數日誌應該如下:

於是又讓提問者確認一下,在remark時間正常的情況下是不是進行了young gc,在remark時間異常的情況下沒有進行young gc,得到的答案是。那麼問題基本上就轉化成了“為什麼在remark之前沒有進行young gc呢”

然後帶著這個問題去Google基本上就比較容易找到答案了,基本可以概述為在執行JNI時候,有可能會導致JVM阻止執行young gc。可以參考:

答案一

答案二

加入引數:+PrintJNIGCStalls可以驗證該問題。

案例二:Young GC 時間飆升很高

這個筆者經歷的一個case,監控&日誌如下:

因為gc log中只能看到GC總時間看不到哪個階段出現問題,所以把垃圾回收齊切換到G1,看到的log如下:

發現Termination比較久,Object copy diff 太大導致的,也就是CPU繁忙程度不一致導致的,修改gc 執行緒數小於 cpu問題解決。

如何判斷是不是Swap區域導致GC異常

如果JVM堆內記憶體大於等於系統記憶體的話,Java程序出現了大量使用Swap區域對GC影響確實比較大。如果發生GC抖動時,系統沒有使用Swap區域或者Java程序沒有使用Swap區域,就能排除Swap原因。

因為我司只對系統使用Swap區域的整體情況做了監控,並未對Java程序使用Swap區域做監控,GC抖動基本上是小機率事件,所以很難從監控做出判斷的。

那麼其他情況,如何大致判斷出來是不是Swap導致的GC異常呢?

首先,我們得了解Swap相關的基本知識。

Swap區域主要解決內部不足的問題,把部分硬碟當做虛擬記憶體使用。

Swap中最關鍵的系統引數:vm.swapiness(0-100),該引數值越小表示當記憶體不足時,傾向於透過回收cache區域,而不是把程序記憶體交換到Swap區域。所以該值應該設定小一點就能減少Swap可能對GC產生的影響,比如我司統一預設設定為1。

Swap記憶體回收演算法使用的是LRU演算法,他會標記處活躍頁面和非活躍頁面,也就是說如果記憶體一直被使用基本上常駐記憶體,不會被交換到Swap。

GC的哪些階段可能受Swap影響young gc

young gc的特色是較為頻繁,基本上每分鐘都會多次。young gc主要有兩個階段,一個是掃描階段、一個是物件複製階段。掃描階段會從根集合掃描標記Eden、From中的存活物件,然後物件複製階段把存活物件copy到To區域中去。

複製階段:因為young gc較為頻繁就會導致Eden、From、To區域不太可能被置換到Swap區域,所以複製階段不太可能受到Swap區域影響;假設young gc不頻繁,那麼在剛剛經歷了掃描階段,Eden、From也肯定會在記憶體中,只有To區域有可能會受到Swap影響。

相比較於複製階段,掃描階段就相對複雜一點。這主要跟根集合有關係,young gc的根集合主要有執行緒上下文、old區域、Class、JNI引用等,像JNI引用、Class等長時間不使用有可能被OS置換到Swap。所以該階段有可能因為Swap影響GC。

cms gc

cms gc主要分為:初始標記、併發標記、併發預清理、重新標記、併發清理等階段,只有初始標記和重新標記會stop the world,所以我們只需要關注這兩個階段即可。

初始標記:該階段標記GC Roots能直接關聯到的物件。所以該階段和young gc的掃描階段類似,也有可能因為Swap影響到GC。

重新標記:由於在併發標記和併發預清理這個階段,使用者執行緒和GC 執行緒併發,假如這個階段使用者執行緒產生了新的物件,總不能被 GC 掉吧。這個階段就是為了讓這些物件重新標記。在這個階段訪問到的記憶體一定是之前剛剛訪問過的,所以這個階段不太可能由Swap區域導致GC異常。

總結

對於CMS GC,如果在remark階段異常行為而InitialMark是正常的,基本上可以排除Swap導致的GC,young gc在copy階段異常而Root Scaning正常也基本上可以排除Swap因素。

我想大家喜歡讓Swap背鍋的原因有兩個:

對Swap如何影響GC以及可能影響到GC哪些階段不太瞭解;GC時間異常情況下,確實較難分析和排除;必須要對GC的具體過程,GC工具等有較為深入的瞭解。

8
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Discourse 安裝 Google Adsense