? ? ? 前陣對底層賬單系統(tǒng)進行了壓測調(diào)優(yōu)檀咙,調(diào)優(yōu)的最后一步--jvm啟動參數(shù)中,減小了線程的堆椏叫希空間:-XX:ThreadStackSize=256K纸淮,縮減至原來的四分之一平斩,效果明顯,不過并沒有調(diào)試其他內(nèi)存空間及gc相關參數(shù)咽块。這次有機會在實際壓測中绘面,調(diào)優(yōu)這一部分內(nèi)容,筆者以cms收集器為例侈沪,將有揭璃、無調(diào)優(yōu)配置情況下的壓測結果進行對比,來分析各項調(diào)用參數(shù)的意義及效果亭罪。
準備工作:
1.調(diào)用查詢接口的測試jar包塘辅,作為dubbo-consumer,依賴了查詢服務的api皆撩,測試module基于maven開發(fā),執(zhí)行maven clean package即可通過編譯得到jar包哲银,本次查詢api使用賬戶查詢接口getUserAccount
2.JMeter:Apache組織開發(fā)的基于Java的壓力測試工具扛吞,添加測試計劃,線程組容量均為200
方案:
無限次請求查詢接口(保證任意時刻并發(fā)量相同)荆责,觀察Error%為0滥比,當請求平穩(wěn)進行時的tps,為該接口吞吐量
實施:
1.jvm中只配置打印gc日志等監(jiān)控參數(shù)
-XX:+PrintGCDetails:打印gc日志詳細信息
-XX:+PrintGCTimeStamps:打印gc發(fā)生時相對jvm啟動的時間戳做院,(后來加入了PrintGCDateStamps盲泛,打印gc發(fā)生的日期)
-Xloggc:設置gc日志的生成位置
壓測數(shù)據(jù)穩(wěn)定后,我們觀察到200線程并發(fā)壓力下键耕,tps可達到1200+寺滚,99%Line600ms左右,我們觀察一下gc日志
這里截取了一次minor gc的數(shù)據(jù)屈雄,兩次gc發(fā)生間隔很短(最短不到1s就發(fā)生第二次minor gc)村视,系統(tǒng)默認為新生代只分配了100到200MB左右空間,老年代也就是200到300MB左右酒奶,可以看出默認分配的空間并不大蚁孔,并且由于新生代容量非常小奶赔,一直在頻繁發(fā)生gc。jvm默認采用PSYoungGen-并行收集器來回收新生代空間杠氢。
2.jvm中加入cms收集器站刑,并手動規(guī)劃jvm空間分配
-Xms4096M:堆容量初始值
-Xmx4096M:堆容量最大值
-Xmn1024M:新生代容量,所以老年代容量 = 堆容量 - 新生代容量 = 3072M
-Xss256K:線程堆棻前伲空間大小
-XX:MaxDirectMemorySize:Direct Buffer Memory大小
-Djava.awt.headless=true:使用缺少外設的系統(tǒng)配置模式
-Dfile.encoding=UTF-8:設置編碼規(guī)范
jmx配置用于遠程管理
-XX:+HeapDumpOutOfMemoryError:當出現(xiàn)OOM時绞旅,打印堆快照
-XX:HeapDumpPath:堆快照打印路徑,建議文件后綴設為hprof愕宋,可被MAT識別
-XX:+DisableExplicitGC:關閉System.gc()
-XX:SurvivorRatio=1:Eden區(qū)與Survivor區(qū)的大小比值
-XX:+UserConcMarkSweepGC:使用CMS收集器
-XX:+UserParNewGC:新生代使用ParNew收集器
-XX:+CMSParallelRemarkEnabled:降低標記停頓
-XX+UseCMSCompactAtFullCollection:在full gc的時候玻靡,對年老代的壓縮
-XX:CMSFullGCsBeforeCompaction=0:full gc后不壓縮老年代內(nèi)存空間
-XX:LargePageSizeInBytes:內(nèi)存頁的大小
-XX:+UseFastAccessorMethods:原始類型的快速優(yōu)化
-XX:+UseCMSInitiatingOccupancyOnly:使用手動定義初始化定義開始CMS收集,禁止hostspot自行觸發(fā)CMS GC
-XX:CMSInitiatingOccupancyFraction=80:老年代使用80%后開始CMS收集
-XX:SoftRefLRUPolicyMSPerMB=0:每兆堆空閑空間中SoftReference的存活時間為0秒
? ? ? ?以上這些配置我們重點關注jvm空間分配相關參數(shù)和收集器相關參數(shù)中贝,首先擴大了堆空間大小至4G囤捻,新生代1G,老年代3G邻寿,直觀上系統(tǒng)可以承載更多實例的創(chuàng)建蝎土,但是同樣也可能造成因對象引用導致的尋址時間增加。另外绣否,手動配置了使用CMS收集器回收老年代誊涯,CMS是一種以最短停頓時間為目標的收集器,使用CMS并不能達到GC效率最高蒜撮,但由于其擁有并發(fā)線程進行標記工作暴构,所以盡可能地降低了GC時服務的停頓時間。而為了保證應用線程不停頓段磨,系統(tǒng)需要更多的CPU資源取逾。總得來說苹支,CMS回收器減少了回收的停頓時間砾隅,但是降低了堆空間的利用率,也降低了吞吐量债蜜,所以使用該收集器的前提是應用程序對停頓比較敏感晴埂,并且有許多生存周期長的對象。我們在此處使用該收集器主要用來觀察手動配置后與默認配置相比有哪些優(yōu)劣寻定。壓測結果如下
我們發(fā)現(xiàn)這種情況下吞吐量有小幅度提高儒洛,并且響應時間降低,那么jvm起了哪些作用呢特姐,我們看一下gc日志
eden晶丘、s1、s2容量被新生代均分為3份,兩個gc間隔時間為2s左右浅浮,已進行了2次full gc沫浆,其余時間一直在執(zhí)行minor gc。兩張圖結合分析滚秩,我們發(fā)現(xiàn)隨著新生代容量的擴大专执,jvm創(chuàng)建實例能力略有提高,同樣200個線程的并發(fā)壓力郁油,同一時間可以承受更多的請求本股,那是不是新生代容量越大吞吐量就越高呢,筆者后來將新生代內(nèi)存調(diào)至3G桐腌,吞吐量不增反降拄显,說明其二者并不是線性相關。我們此時可以確定的是:jvm內(nèi)存容量要適當增大案站,并且內(nèi)存分配比例要盡可能符合jvm對對象的實際創(chuàng)建情況躬审。
總結:
? ? ? ?jvm參數(shù)是靈活使用jvm的關鍵,我們在使用時需要謹慎添加蟆盐,當然如果搭配的好承边,至少在系統(tǒng)內(nèi)部服務層面,性能會有客觀的提升石挂。但這也是想表達的另一個觀點博助,如何配置jvm內(nèi)存空間,選擇哪些gc收集器組合痹愚,并沒有絕對的標準富岳,絕對的好與不好,都是在多次的權衡拯腮、搭配下城瞎,產(chǎn)生對你所運行的服務一個相對好的效果。jvm調(diào)優(yōu)路漫漫疾瓮,吾將繼續(xù)求索。