JVM引數設定的一些參考方法
問題:
新上線一個java服務,或者是RPC或者是WEB站點, 記憶體的設定該怎麼設定呢?設定成多大比較合適,既不浪費記憶體,又不影響效能呢?
分析:
依據的原則是根據Java Performance裡面的推薦公式來進行設定。
具體來講:
Java整個堆大小設定,Xmx 和 Xms設定為老年代存活物件的3-4倍,即FullGC之後的老年代記憶體佔用的3-4倍
永久代 PermSize和MaxPermSize設定為老年代存活物件的1.2-1.5倍。
年輕代Xmn的設定為老年代存活物件的1-1.5倍。
老年代的記憶體大小設定為老年代存活物件的2-3倍。
BTW:
1、Sun官方建議年輕代的大小為整個堆的3/8左右, 所以按照上述設定的方式,基本符合Sun的建議。
2、堆大小=年輕代大小+年老代大小, 即xmx=xmn+老年代大小 。 Permsize不影響堆大小。
3、為什麼要按照上面的來進行設定呢? 沒有具體的說明,但應該是根據多種調優之後得出的一個結論。
如何確認老年代存活物件大小?
方式1(推薦/比較穩妥):
JVM引數中新增GC日誌,GC日誌中會記錄每次FullGC之後各代的記憶體大小,觀察老年代GC之後的空間大小。可觀察一段時間內(比如2天)的FullGC之後的記憶體情況,根據多次的FullGC之後的老年代的空間大小資料來預估FullGC之後老年代的存活物件大小(可根據多次FullGC之後的記憶體大小取平均值)
方式2:(強制觸發FullGC, 會影響線上服務,慎用)
方式1的方式比較可行,但需要更改JVM引數,並分析日誌。同時,在使用CMS回收器的時候,有可能不能觸發FullGC(只發生CMS GC),所以日誌中並沒有記錄FullGC的日誌。在分析的時候就比較難處理。
BTW:使用jstat -gcutil工具來看FullGC的時候, CMS GC是會造成2次的FullGC次數增加。 具體可參見之前寫的一篇關於jstat使用的文章
所以,有時候需要強制觸發一次FullGC,來觀察FullGC之後的老年代存活物件大小。
注:強制觸發FullGC,會造成線上服務停頓(STW),要謹慎,建議的操作方式為,在強制FullGC前先把服務節點摘除,FullGC之後再將服務掛回可用節點,對外提供服務
在不同時間段觸發FullGC,根據多次FullGC之後的老年代記憶體情況來預估FullGC之後的老年代存活物件大小
如何觸發FullGC ?
使用jmap工具可觸發FullGC
jmap -dump:live,format=b,file=heap.bin <pid> 將當前的存活物件dump到檔案,此時會觸發FullGC
jmap -histo:live <pid> 列印每個class的例項數目,記憶體佔用,類全名資訊.live子引數加上後,只統計活的物件數量. 此時會觸發FullGC
具體操作例項:
以我司的一個RPC服務為例。
BTW:剛上線的新服務,不知道該設定多大的記憶體的時候,可以先多設定一點記憶體,然後根據GC之後的情況來進行分析。
初始JVM記憶體引數設定為: Xmx=2G Xms=2G xmn=1G
使用jstat 檢視當前的GC情況。如下圖:
YGC平均耗時: 173.825s/15799=11ms
FGC平均耗時:0.817s/41=19.9ms
平均大約10-20s會產生一次YGC
看起來似乎不錯,YGC觸發的頻率不高,FGC的耗時也不高,但這樣的記憶體設定是不是有些浪費呢?
為了快速看資料,我們使用了方式2,產生了幾次FullGC,FullGC之後,使用的jmap -heap 來看的當前的堆記憶體情況(也可以根據GC日誌來看)
heap情況如下圖:(命令 : jmap -heap <pid>)
上圖中的concurrent mark-sweep generation即為老年代的記憶體描述。
老年代的記憶體佔用為100M左右。 按照整個堆大小是老年代(FullGC)之後的3-4倍計算的話,設定各代的記憶體情況如下:
Xmx=512m Xms=512m Xmn=128m PermSize=128m 老年代的大小為 (512-128=384m)為老年代存活物件大小的3倍左右
調整之後的,heap情況
GC情況如下:
YGC 差不多在10s左右觸發一次。每次YGC平均耗時大約9.41ms。可接受。
FGC平均耗時:0.016s/2=8ms
整體的GC耗時減少。但GC頻率比之前的2G時的要多了一些。
注: 看上述GC的時候,發現YGC的次數突然會增多很多個,比如 從1359次到了1364次。具體原因是?
總結:
在記憶體相對緊張的情況下,可以按照上述的方式來進行記憶體的調優, 找到一個在GC頻率和GC耗時上都可接受的一個記憶體設定,可以用較小的記憶體滿足當前的服務需要
但當記憶體相對寬裕的時候,可以相對給服務多增加一點記憶體,可以減少GC的頻率,GC的耗時相應會增加一些。 一般要求低延時的可以考慮多設定一點記憶體, 對延時要求不高的,可以按照上述方式設定較小記憶體。
補充:
永久代(方法區)並不在堆內,所以之前有看過一篇文章中描述的 整個堆大小=年輕代+年老代+永久代的描述是不正確的。
相關文章
- Java 動態設定 JVM 引數的方法JavaJVM
- JVM常見引數設定JVM
- JVM引數設定大氣JVM
- docker 配置引數參考Docker
- 2.7.11 檢視引數設定的方法
- 詳情頁產品引數模組設計參考
- 檢視JVM預設引數及微調JVM啟動引數JVM
- JVM快速調優手冊v1.0之六:JVM引數設定、分析JVM
- mysqldump常見使用場景及引數參考MySql
- OceanBase學習之路48|最佳效能引數的配置參考
- 檢視JVM預設配置引數JVM
- C#:設定CefSharp的一些引數,比如忽略安全證書C#
- 一個可以參考的JVM記憶體分配JVM記憶體
- 常用JVM引數JVM
- 方法(函式)的定義與引數函式
- 常用的jvm配置引數 :永久區引數配置JVM
- tomcat vm 引數設定Tomcat
- JVM調優引數、方法、工具以及案例總結JVM
- curl CURLOPT_WRITEFUNCTION 的引數設定Function
- 複習PHP-語言參考-預定義變數PHP變數
- JVM引數以及用法JVM
- JavaScript Math(數學) 參考JavaScript
- pandas引數設定小技巧
- Metasploit設定VERBOSE引數技巧
- Metasploit設定HttpTrace引數技巧HTTP
- Metasploit設定LHOST引數技巧
- MySQL的配置檔案的引數設定MySql
- Javascript 定時器呼叫傳遞引數的方法JavaScript定時器
- Flink提交Job的方式以及引數設定
- 19c exadata不能設定的引數
- JVM 引數調優(qbit)JVM
- JVM實用引數系列JVM
- JVM常用調優引數JVM
- SOLIDWORKS引數化設計方法Solid
- 2.6.10 設定許可證引數
- [20200220]windows設定keepalive引數.txtWindows
- 方法的過載、可變形參的方法、方法的引數值傳遞機制、遞迴方法遞迴
- 電商 | 分享一組詳情頁產品引數模組參考