jvm參數(shù)解析(含調(diào)優(yōu)過程)

? ? ? 前陣對(duì)底層賬單系統(tǒng)進(jìn)行了壓測(cè)調(diào)優(yōu),調(diào)優(yōu)的最后一步--jvm啟動(dòng)參數(shù)中,減小了線程的堆棧空間:-XX:ThreadStackSize=256K,縮減至原來的四分之一,效果明顯,不過并沒有調(diào)試其他內(nèi)存空間及gc相關(guān)參數(shù)。這次有機(jī)會(huì)在實(shí)際壓測(cè)中,調(diào)優(yōu)這一部分內(nèi)容,筆者以cms收集器為例,將有、無調(diào)優(yōu)配置情況下的壓測(cè)結(jié)果進(jìn)行對(duì)比,來分析各項(xiàng)調(diào)用參數(shù)的意義及效果。


準(zhǔn)備工作:

1.調(diào)用查詢接口的測(cè)試jar包,作為dubbo-consumer,依賴了查詢服務(wù)的api,測(cè)試module基于maven開發(fā),執(zhí)行maven clean package即可通過編譯得到j(luò)ar包,本次查詢api使用賬戶查詢接口getUserAccount

2.JMeter:Apache組織開發(fā)的基于Java的壓力測(cè)試工具,添加測(cè)試計(jì)劃,線程組容量均為200

方案:

無限次請(qǐng)求查詢接口(保證任意時(shí)刻并發(fā)量相同),觀察Error%為0,當(dāng)請(qǐng)求平穩(wěn)進(jìn)行時(shí)的tps,為該接口吞吐量

實(shí)施:

1.jvm中只配置打印gc日志等監(jiān)控參數(shù)

-XX:+PrintGCDetails:打印gc日志詳細(xì)信息

-XX:+PrintGCTimeStamps:打印gc發(fā)生時(shí)相對(duì)jvm啟動(dòng)的時(shí)間戳,(后來加入了PrintGCDateStamps,打印gc發(fā)生的日期)

-Xloggc:設(shè)置gc日志的生成位置

壓測(cè)聚合報(bào)告

壓測(cè)數(shù)據(jù)穩(wěn)定后,我們觀察到200線程并發(fā)壓力下,tps可達(dá)到1200+,99%Line600ms左右,我們觀察一下gc日志

這里截取了一次minor gc的數(shù)據(jù),兩次gc發(fā)生間隔很短(最短不到1s就發(fā)生第二次minor gc),系統(tǒng)默認(rèn)為新生代只分配了100到200MB左右空間,老年代也就是200到300MB左右,可以看出默認(rèn)分配的空間并不大,并且由于新生代容量非常小,一直在頻繁發(fā)生gc。jvm默認(rèn)采用PSYoungGen-并行收集器來回收新生代空間。

2.jvm中加入cms收集器,并手動(dòng)規(guī)劃jvm空間分配

-Xms4096M:堆容量初始值

-Xmx4096M:堆容量最大值

-Xmn1024M:新生代容量,所以老年代容量 = 堆容量 - 新生代容量 = 3072M

-Xss256K:線程堆??臻g大小

-XX:MaxDirectMemorySize:Direct Buffer Memory大小

-Djava.awt.headless=true:使用缺少外設(shè)的系統(tǒng)配置模式

-Dfile.encoding=UTF-8:設(shè)置編碼規(guī)范

jmx配置用于遠(yuǎn)程管理

-XX:+HeapDumpOutOfMemoryError:當(dāng)出現(xiàn)OOM時(shí),打印堆快照

-XX:HeapDumpPath:堆快照打印路徑,建議文件后綴設(shè)為hprof,可被MAT識(shí)別

-XX:+DisableExplicitGC:關(guān)閉System.gc()

-XX:SurvivorRatio=1:Eden區(qū)與Survivor區(qū)的大小比值

-XX:+UserConcMarkSweepGC:使用CMS收集器

-XX:+UserParNewGC:新生代使用ParNew收集器

-XX:+CMSParallelRemarkEnabled:降低標(biāo)記停頓

-XX+UseCMSCompactAtFullCollection:在full gc的時(shí)候,對(duì)年老代的壓縮

-XX:CMSFullGCsBeforeCompaction=0:full gc后不壓縮老年代內(nèi)存空間

-XX:LargePageSizeInBytes:內(nèi)存頁的大小

-XX:+UseFastAccessorMethods:原始類型的快速優(yōu)化

-XX:+UseCMSInitiatingOccupancyOnly:使用手動(dòng)定義初始化定義開始CMS收集,禁止hostspot自行觸發(fā)CMS GC

-XX:CMSInitiatingOccupancyFraction=80:老年代使用80%后開始CMS收集

-XX:SoftRefLRUPolicyMSPerMB=0:每兆堆空閑空間中SoftReference的存活時(shí)間為0秒

? ? ? ?以上這些配置我們重點(diǎn)關(guān)注jvm空間分配相關(guān)參數(shù)和收集器相關(guān)參數(shù),首先擴(kuò)大了堆空間大小至4G,新生代1G,老年代3G,直觀上系統(tǒng)可以承載更多實(shí)例的創(chuàng)建,但是同樣也可能造成因?qū)ο笠脤?dǎo)致的尋址時(shí)間增加。另外,手動(dòng)配置了使用CMS收集器回收老年代,CMS是一種以最短停頓時(shí)間為目標(biāo)的收集器,使用CMS并不能達(dá)到GC效率最高,但由于其擁有并發(fā)線程進(jìn)行標(biāo)記工作,所以盡可能地降低了GC時(shí)服務(wù)的停頓時(shí)間。而為了保證應(yīng)用線程不停頓,系統(tǒng)需要更多的CPU資源??偟脕碚f,CMS回收器減少了回收的停頓時(shí)間,但是降低了堆空間的利用率,也降低了吞吐量,所以使用該收集器的前提是應(yīng)用程序?qū)νnD比較敏感,并且有許多生存周期長的對(duì)象。我們?cè)诖颂幨褂迷撌占髦饕脕碛^察手動(dòng)配置后與默認(rèn)配置相比有哪些優(yōu)劣。壓測(cè)結(jié)果如下

我們發(fā)現(xiàn)這種情況下吞吐量有小幅度提高,并且響應(yīng)時(shí)間降低,那么jvm起了哪些作用呢,我們看一下gc日志

eden、s1、s2容量被新生代均分為3份,兩個(gè)gc間隔時(shí)間為2s左右,已進(jìn)行了2次full gc,其余時(shí)間一直在執(zhí)行minor gc。兩張圖結(jié)合分析,我們發(fā)現(xiàn)隨著新生代容量的擴(kuò)大,jvm創(chuàng)建實(shí)例能力略有提高,同樣200個(gè)線程的并發(fā)壓力,同一時(shí)間可以承受更多的請(qǐng)求,那是不是新生代容量越大吞吐量就越高呢,筆者后來將新生代內(nèi)存調(diào)至3G,吞吐量不增反降,說明其二者并不是線性相關(guān)。我們此時(shí)可以確定的是:jvm內(nèi)存容量要適當(dāng)增大,并且內(nèi)存分配比例要盡可能符合jvm對(duì)對(duì)象的實(shí)際創(chuàng)建情況。


總結(jié):

? ? ? ?jvm參數(shù)是靈活使用jvm的關(guān)鍵,我們?cè)谑褂脮r(shí)需要謹(jǐn)慎添加,當(dāng)然如果搭配的好,至少在系統(tǒng)內(nèi)部服務(wù)層面,性能會(huì)有客觀的提升。但這也是想表達(dá)的另一個(gè)觀點(diǎn),如何配置jvm內(nèi)存空間,選擇哪些gc收集器組合,并沒有絕對(duì)的標(biāo)準(zhǔn),絕對(duì)的好與不好,都是在多次的權(quán)衡、搭配下,產(chǎn)生對(duì)你所運(yùn)行的服務(wù)一個(gè)相對(duì)好的效果。jvm調(diào)優(yōu)路漫漫,吾將繼續(xù)求索。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容