摘要:內存設置現在線上業務系統基本物理內存都是夠用的,不過物盡其用,我們調優就是爭取讓每空間都發揮出最大的作用。區總內存減去一個區的大小不宜過大,否則可能把物理內存耗光。
在生產系統中,高吞吐和低延遲一直都是JVM調優的最終目標,但這兩者恰恰又是相悖的,魚和熊掌不可兼得,所以在調優之前要清楚舍誰而取誰。一般計算任務和組件服務會偏向高吞吐,而web展示則偏向低延遲才會帶來更好的用戶體驗。
本文從性能和經驗上來分享一下JVM參數的設置。
調優之前可以先用-XX:+PrintFlagsFinal來查看虛擬機是否默認開啟某參數,不同版本的JDK可能虛擬機默認開啟的參數也略有不同,新學習一條神奇的參數的時候可以先去查找一下參數是否默認開啟了。
$ java -server -XX:+PrintCommandLineFlags |grep XXXXXXX
也可以通過jinfo口令 jinfo -flags [pid]來查看
GC策略目前來看還是CMS當道,吞吐率和響應時間闊以兼顧,G1嘛,雞丸雞丸,至今并沒有展現出one的實力,不過據貴里某P8講G1在大堆(20G+)下表現更突出,停頓會顯著降低,可能之后隨著高內存越來越經濟和普及,G1才能名副其實的稱為雞one。
廢話少說,
-XX:+UseConcMarkSweepGC
設置CMS做為垃圾收集,CMS開啟后默認的新生代回收是ParNew,如果CMS出現“Concurrent Mode Failure”了還會啟用Serial Old做備胎。
-XX:CMSInitiatingOccupancyFraction=75
默認值是68,這個可以根據實際調優目標來調整,這個參數就比較應開始提到的,調優目標是降低延遲還是提高吞吐,如果是為了降低單次GC延遲,那么這個值闊以再往低了調一些,不過調的太高可能導致老年代剩余空間不夠招呼并發收集產生的浮動垃圾而頻繁的觸發Full GC。
-XX:+UseCMSInitiatingOccupancyOnly
使用CMS的話這個參數一定要加上,一定要加上,一定要加上,重要的事情說三遍,否則虛擬機后面還是會自作聰明的自己計算上個參數的比值。
-XX:MaxTenuringThreshold=5
默認15,這個值是設置新生代對象存活了多少次young GC后可以進入老年代,值設的高的話可以使老年代增長緩慢,但YGC的次數會明顯增多,如果清楚YGC的執行頻率和大多數對象的最長生命周期,這個值可以設低些,讓那些對象早點進入老年代。
可以用-XX:+PrintTenuringDistribution來觀察一段時間,然后調整合適的值。
ps:有一種野路子是此值設為0,新生代GC次數少,速度快,就是老年代GC會更加頻繁一些,不過也最大利用了并發GC。不過我沒在生產這么搞過,效果有待驗證。
-XX:+ExplicitGCInvokesConcurrent
這個參數是用來代替,-XX:DisableExplicitGC的,NIO許多地方會顯示的調用System.gc()來觸發一次Full GC。許多時候別的地方優化一萬點都賠不起這兒調上幾次的。ExplicitGCInvokesConcurrent這個參數是配合CMS使用的,開啟后System.gc()還是會觸發Full GC,不過并不是一個完全的stop-the-world的Full GC,而是并發的CMS GC。
內存設置現在線上業務系統基本物理內存都是夠用的,不過物盡其用,我們調優就是爭取讓每M空間都發揮出最大的作用。內存的設置還是最直觀見效的。
-Xmx500m ,-Xms500m
最大堆內存和最小堆內存,這兩個值要設的一致,避免虛擬機還要動態的計算分配內存空間。
PS:堆也不是越大越好,大堆帶來的后果就是單次GC會較長。
-Xmn250m
新生代大小,非G1收集器可以設置這個值,G1的官方建議是不要顯示分配新生代和老年代空間大小,因為G1會通過網格化內存來動態分配new/old區,官方認為不設置new size是最佳實踐。
-Xss2m
每個線程的棧空間大小,默認值是1m,一般不需要設置,除非有遞歸方法存在可能會爆棧。
-XX:PermSize=128m,-XX:MaxPermSize=256m
JDK8之前永久代的空間設置,Spring框架了大量依賴AOP的實現都用的動態代理生成字節碼,所以設個最大值求保險。
不過JDK8之后取消了永久代,改為元空間(MetaSpace),這塊屬于本地內存,理論上可以利用系統剩余的所有內存,不過跑了多個實例的話還是要設置一下為妙:
-XX:MetaspaceSize=128m,-XX:MaxMetaspaceSize=256m
-XX:MaxDirectMemorySize=128m
這個屬于對外內存,可以合理控制大小。Heap區總內存減去一個Survivor區的大小,不宜過大,否則可能heap size + Direct Memory Size把物理內存耗光。
-XX:SurvivorRatio=7
默認是8,新生代中Eden與Survivor的比值,過大的話可能Survivor存不下臨時對象而頻繁觸發分配擔保。可以根據GC日志看實際情況。
PS:
關于內存大小的設置完全要根據各個機器和應用自身的情況來設置。
可以通過jstat -gc [pid] 2000 30,每2s輸出一次一共輸出30次內存情況,看看各個區域增長的速度,最大空間等數據來修改內存設置。
監控參數還是需要的,不然有時候線上偶爾OOM了真的不好重現。
-XX:+HeapDumpOnOutOfMemoryError,-XX:HeapDumpPath={path}
OOM的時候會輸出dump快照到{path}目錄,只需要指向目錄,文件名JVM會保持唯一性。
-XX:+PrintGCDetails,-Xloggc:logs/gc.log,-XX:+PrintGCTimeStamps,-XX:+PrintGCDateStamps
打印GC詳細記錄,-XX:+PrintGC 這個口令是簡單GC日志,為了更容易定位問題,我們開啟Details模式,-Xloggc是把gc日志輸出到指定文件。
-XX:+PrintGCTimeStamps顯示的時間代表JVM啟動至記錄日志的時間。
-XX:+PrintGCDateStamps則會添加上每行信息的絕對日期。
其實開啟了-Xloggc的話會隱式的開啟-XX:+PrintGCTimeStamps,不過為了防止各版本JVM改動差異,還是顯示的設置出來保險。
-XX:-OmitStackTraceInFastThrow
這是個比較容易被忽略的參數,而沒有經驗的話又往往很難定位到原因。
JDK5之后JVM對異常做了一個優化,對于一些頻繁拋出的異常,JIT重新編譯后會拋出沒有堆棧信息的異常,-server模式下是默認開啟的,因此在頻繁拋出某個異常一段時間后,該優化開始起作用,即只拋出沒有堆棧的異常信息。
但由于該優化是JIT編譯后才啟用的,所以開始該異常的拋出是有完整堆棧信息的,但運行一段時間可能發現沒有任何堆棧信息,很難定位,初次遇到很容易摸不到頭腦。
可以使用-XX:-OmitStackTraceInFastThrow來關閉該項優化。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76120.html
摘要:原文鏈接本篇是專家系列的第三篇。但是,請記住調優是不得已時的選擇。縮短耗時的單次執行與相比,耗時有較明顯的增加。創建文件過程中,進程會中斷,因此不要在正常運行時系統上做此操作。因此校驗結果并根據具體的服務需要,決定是否要進行調優。 原文鏈接:http://www.cubrid.org/blog/dev-platform/how-to-tune-java-garbage-collecti...
面試官:今天要不來聊聊JVM調優相關的吧?面試官:你曾經在生產環境下有過調優JVM的經歷嗎?候選者:沒有面試官:...候選者:嗯...是這樣的,我們一般優化系統的思路是這樣的候選者:1. 一般來說關系型數據庫是先到瓶頸,首先排查是否為數據庫的問題候選者:(這個過程中就需要評估自己建的索引是否合理、是否需要引入分布式緩存、是否需要分庫分表等等)候選者:2. 然后,我們會考慮是否需要擴容(橫向和縱向都...
閱讀 2124·2019-08-29 16:53
閱讀 2699·2019-08-29 16:07
閱讀 2042·2019-08-29 13:13
閱讀 3267·2019-08-26 13:57
閱讀 1331·2019-08-26 13:31
閱讀 2433·2019-08-26 13:22
閱讀 1221·2019-08-26 11:43
閱讀 2084·2019-08-23 17:14