咱們的遊戲上線之初,常常有玩家反饋卡,或者有網絡延遲等現象,形成用戶流失等現象,這時候我就想到是否是多是以前的jvm配置有問題,或者存在內存泄露等問題。java
登入生產環境,使用命令,由於這時候並無打gc的log,因此只能觀察現象。shell
jstat -gcutil 27084 250 20
查看gc狀態
數組
說明:網絡
S0 | S1 | E | O | P | YGC | YGCT | FGC | FGCT | GCT |
---|---|---|---|---|---|---|---|---|---|
54.62 | 0.00 | 42.87 | 43.52 | 86.24 | 1792 | 5.093 | 33 | 7.670 | 12.763 |
S0:新生代的susvivor0區,空間使用率爲54..62%jvm
S1:新生代的susvivor1區,空間使用率爲0.00%(由於尚未執行第二次minor收集)性能
E:eden區,空間使用率42.87%測試
O:舊生代,空間使用率43.52%優化
P:持久帶,空間使用率86.24%spa
YGC:minor gc執行次數1792次操作系統
YGCT:minor gc耗費的時間5.093毫秒
FGC:full gc執行次數33
FGCT:full gc耗費的時間7.670毫秒
GCT:gc耗費的總時間12.763毫秒
發現其實主要是full gc頻率太高,爲何會致使這個緣由呢,我首先想到的是是否是老生代分配的太低,就着手分配老生代的比例
然而並無解決這個問題,發現YGC持續升高,而FGC也會逐漸上來,暫時解決了問題的表象而已。
使用命令jstat -gccapacity:能夠顯示,VM內存中三代(young,old,perm)對象的使用和佔用大小,如:PGCMN顯示的是最小perm的內存使用量,PGCMX顯示的是perm的內存最大使用量,PGC是當前新生成的perm內存佔用量,PC是但前perm內存佔用量。其餘的能夠根據這個類推, OC是old內純的佔用量。
看了一下jvm內存分配狀況,發現一共新生代只分配了50M左右,發現原來以前使用的啓動腳本並無設置jvm啓動參數
先把Jvm參數調整,gc log文件夾設置
JAVA_OPTS="-Xms2048m -Xmx2048m -XX:PermSize=64m -XX:MaxPermSize=256m -verbose:gc -Xloggc:/home/admin/logs/gc.log"
生產環境Java應用的jvm參數Xms與Xmx保持一致,避免因所使用的Java堆內存不夠致使頻繁full gc以及full gc中因動態調節Java堆大小而耗費延長其週期。
查看下圖,FGC已經明顯降低到正常水平
學好JVM能夠從JVM參數開始:
參數名稱 | 含義 默認值 |
---|---|
-Xms | 初始堆大小 物理內存的1/64(<1GB) 默認(MinHeapFreeRatio參數能夠調整)空餘堆內存小於40%時,JVM就會增大堆直到-Xmx的最大限制. |
-Xmx | 最大堆大小 物理內存的1/4(<1GB) 默認(MaxHeapFreeRatio參數能夠調整)空餘堆內存大於70%時,JVM會減小堆直到 -Xms的最小限制 |
-Xmn | 年輕代大小(1.4or lator)注意:此處的大小是(eden+ 2 survivor space).與jmap -heap中顯示的New gen是不一樣的。整個堆大小=年輕代大小 + 年老代大小 + 持久代大小.增大年輕代後,將會減少年老代大小.此值對系統性能影響較大,Sun官方推薦配置爲整個堆的3/8 |
-XX:NewSize | 設置年輕代大小(for 1.3/1.4) |
-XX:MaxNewSize | 年輕代最大值(for 1.3/1.4) |
-XX:PermSize | 設置持久代(perm gen)初始值 物理內存的1/64 |
-XX:MaxPermSize | 設置持久代最大值 物理內存的1/4 |
-Xss | 每一個線程的堆棧大小,JDK5.0之後每一個線程堆棧大小爲1M,之前每一個線程堆棧大小爲256K.更具應用的線程所需內存大小進行 調整.在相同物理內存下,減少這個值能生成更多的線程.可是操做系統對一個進程內的線程數仍是有限制的,不能無限生成,經驗值在3000~5000左右,通常小的應用, 若是棧不是很深, 應該是128k夠用的 大的應用建議使用256k。這個選項對性能影響比較大,須要嚴格的測試。(校長)和threadstacksize選項解釋很相似,官方文檔彷佛沒有解釋,在論壇中有這樣一句話:"」-Xss is translated in a VM flag named ThreadStackSize」通常設置這個值就能夠了。 |
-XX:ThreadStackSize | Thread Stack Size (0 means use default stack size) [Sparc: 512; Solaris x86: 320 (was 256 prior in 5.0 and earlier); Sparc 64 bit: 1024; Linux amd64: 1024 (was 0 in 5.0 and earlier); all others 0.] |
-XX:NewRatio | 年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代) -XX:NewRatio=4表示年輕代與年老代所佔比值爲1:4,年輕代佔整個堆棧的1/5Xms=Xmx而且設置了Xmn的狀況下,該參數不須要進行設置。 |
-XX:SurvivorRatio | Eden區與Survivor區的大小比值 設置爲8,則兩個Survivor區與一個Eden區的比值爲2:8,一個Survivor區佔整個年輕代的1/10 |
-XX:LargePageSizeInBytes | 內存頁的大小不可設置過大, 會影響Perm的大小 =128m |
-XX:+UseFastAccessorMethods | 原始類型的快速優化 |
-XX:+DisableExplicitGC | 關閉System.gc() 這個參數須要嚴格的測試 |
-XX:MaxTenuringThreshold | 垃圾最大年齡 若是設置爲0的話,則年輕代對象不通過Survivor區,直接進入年老代. 對於年老代比較多的應用,能夠提升效率.若是將此值設置爲一個較大值,則年輕代對象會在Survivor區進行屢次複製,這樣能夠增長對象再年輕代的存活 時間,增長在年輕代即被回收的機率,該參數只有在串行GC時纔有效. |
-XX:+AggressiveOpts | 加快編譯 |
-XX:+UseBiasedLocking | 鎖機制的性能改善 |
-Xnoclassgc | 禁用垃圾回收 |
-XX:SoftRefLRUPolicyMSPerMB | 每兆堆空閒空間中SoftReference的存活時間 1s softly reachable objects will remain alive for some amount of time after the last time they were referenced. The default value is one second of lifetime per free megabyte in the heap |
-XX:PretenureSizeThreshold | 對象超過多大是直接在舊生代分配 0 單位字節 新生代採用Parallel Scavenge GC時無效,另外一種直接在舊生代分配的狀況是大的數組對象,且數組中無外部引用對象. |
-XX:TLABWasteTargetPercent | TLAB佔eden區的百分比 1% |
-XX:+CollectGen0First | FullGC時是否先YGC false |