遊戲服務器JVM優化

最近開始優化頁遊服務端的性能,一些心得總結一下。如今的服務器硬件愈來愈好,幾十G內存,十幾個CPU。當硬件不是瓶頸的時候,若是讓程序發揮最大效用就成了咱們須要考慮的問題。就遊戲服務器來講,得知足幾個要求,高負載,低延時。特別是在開服當天,大量用戶會涌進來,可能給服務器形成壓力。使用Java做爲服務器語言,除了程序自己的性能外,JVM的配置也直接影響到系統性能。java

參數調優算法

入門級別的配置通常是:java -server -Xmx5000m Xms5000m
服務器端的jvm運行程序記得都最好加上 -server 不少默認參數都會根據這個運行模式來優化。這裏設置了最大內存和最小內存,通常都是配置成相同的,能夠減小內存申請和伸縮帶來的性能損耗服務器

加入垃圾回收算法的配置:java -server -Xmx5000m -Xms5000m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
關於垃圾回收的具體算法介紹我這裏就不詳細描述了,咱們都有一個常識,就是儘可能減小JVM的full gc的次數和時間,由於full gc 會致使整個系統的暫停(stop the world).爲此,咱們爲老年代選擇了UseConcMarkSweepGC 選擇了併發gc算法,也爲新生代選擇了多線程的並行gc算法UseParNewGC。多線程

設置新生代的內存大小 java -server -Xmx5000m -Xms5000m -Xmn800m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
Xmn是新生代的內存大小,包括(eden+ 2 survivor space)。這個參數設置直接影響系統的響應速度。在java程序中new一個對象,首先是放在eden區域,eden滿了後,觸發gc,存活下來的對象被拷貝到survivor區。通過若干次yong gc後,若是依然存活下來,就會進入老年代。新生代設置大了,會致使一次yong gc的時間消耗大,設置小了,又會很快滿了,致使yong gc的頻率太高。新生代不宜設置過大,由於新生代大了,老年代的內存就小了,老年代內存小,會致使full gc發生的頻率變大。Xmn也沒有一個確切的算法,根據你自身的業務系統決定的。我在設置的遊戲服務器的時候,通常採用模擬大量併發用戶的行爲,調整Xmn的大小,同時監控gc的時間和頻率,選擇一個合適的大小。下面我會提到怎麼用工具來監控gc。架構

設置一些額外的高級參數 java -server -Xmx5000m -Xms5000m -Xmn800m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70
使用CMS進行老年代gc,會容易致使一些內存碎片,致使內存利用率下降,爲此,加入 UseCMSCompactAtFullCollection 能夠保證在full gc時進行內存壓縮,減小內存碎片,系統默認爲開啓true。CMSInitiatingOccupancyFraction=70 表示老年代內存達到70%時觸發。這個參數要特別當心,默認爲68%,設置得太小會致使full gc沒有完成,yong gc的對象遷移過來,致使整個老年代內存都滿了併發

5.-XX:+UseCompressedOops JVM優化之壓縮普通對象指針(CompressedOops),一般64位JVM消耗的內存會比32位的大1.5倍,這是由於對象指針在64位架構下,長度會翻倍(更寬的尋址)。對於那些將要從32位平臺移植到64位的應用來講,平白無辜多了1/2的內存佔用,這是開發者不肯意看到的。系統默認爲開啓true。jvm

6.-XX:+PrintCommandLineFlags 。這個參數的做用是顯示出VM初始化完畢後全部跟最初的默認值不一樣的參數及它們的值。工具

  1. -XX:+PrintFlagsFinal 。前一個參數只顯示跟默認值不一樣的,而這個參數則能夠顯示全部可設置的參數及它們的值。

8.-XX:+PrintFlagsInitial 。這個參數顯示在處理參數以前全部可設置的參數及它們的值性能

查看默認值的方式統一爲
java -server -Xmx1024m -Xms1024m -XX:+UseConcMarkSweepGC -XX:+PrintFlagsFinal -version| grep ParallelGCThreads
JVM默認垃圾回收策略,
針對年輕代:
UseParallelGC true(默認)
UseParNewGC false
UseSerialGC false
-XX:+UseParallelGC:選擇垃圾收集器爲並行收集器。此配置僅對年輕代有效。能夠同時並行多個垃圾收集線程,但此時用戶線程必須中止。
-XX:+UseParNewGC:設置年輕代爲多線程收集。可與CMS收集同時使用。在serial基礎上實現的多線程收集器。
針對年老代:
UseParallelOldGC true(默認)
UseConcMarkSweepGC false
-XX:-UseConcMarkSweepGC 對老生代採用併發標記交換算法進行GC
-XX:+UseParallelOldGC:配置年老代垃圾收集方式爲並行收集。當-XX:-UseParallelGC啓用時該項自動啓用
工具測試

jstat 用來實時查看gc的狀態,
用法:jstat -gcutil 進程號 時間(毫秒)。結果以下:

裏面列出每一個區間的內存大小,新生代gc的次數和時間,老年代gc的次數和時間。這裏都能反映出你的JVM的運行情況

jmap 用於查看java進程的對象情況
用法:jmap -histo:live 進程id 。能夠打印每一個類的實例數量,內存大小

用法:jmap -dump:format=b,file=log.bin 進程id 這個命令特別有用,能夠將jvm的整個內存鏡像拷貝下來,用於分析每一個對象佔用的內存情況。當你的java進程崩潰了,用這個方法,能夠分析出哪些對象是罪魁禍首

jstack 用於查看java進程id的堆棧信息
用法:jstack 進程id 這個工具對於查看死循環的線程頗有效,能夠直接找出是哪一個線程在哪一個方法內死循環了

總結

JVM的參數有不少,大部分咱們都不須要去設置和優化。若是你的程序沒有問題,就不要去折騰。若是你要優化,必定要有相應的測試流程來支撐。

相關文章
相關標籤/搜索