最近開始優(yōu)化頁游服務(wù)端的性能,一些心得總結(jié)一下?,F(xiàn)在的服務(wù)器硬件越來越好,幾十G內(nèi)存,十幾個(gè)CPU。當(dāng)硬件不是瓶頸的時(shí)候,如果讓程序發(fā)揮最大效用就成了我們需要考慮的問題。就游戲服務(wù)器來說,得滿足幾個(gè)要求,高負(fù)載,低延時(shí)。特別是在開服當(dāng)天,大量用戶會(huì)涌進(jìn)來,可能給服務(wù)器造成壓力。使用Java作為服務(wù)器語言,除了程序本身的性能外,JVM的配置也直接影響到系統(tǒng)性能。 參數(shù)調(diào)優(yōu) 1 入門級(jí)別的配置一般是:java -server -Xmx5000m Xms5000m 服務(wù)器端的jvm運(yùn)行程序記得都最好加上 -server 很多默認(rèn)參數(shù)都會(huì)根據(jù)這個(gè)運(yùn)行模式來優(yōu)化。這里設(shè)置了最大內(nèi)存和最小內(nèi)存,一般都是配置成相同的,可以減少內(nèi)存申請(qǐng)和伸縮帶來的性能損耗 2 加入垃圾回收算法的配置:java -server -Xmx5000m -Xms5000m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC 關(guān)于垃圾回收的具體算法介紹我這里就不詳細(xì)描述了,可以參考我以前的文章 我們都有一個(gè)常識(shí),就是盡量減少JVM的full gc的次數(shù)和時(shí)間,因?yàn)?/font>full gc 會(huì)導(dǎo)致整個(gè)系統(tǒng)的暫停(stop the world).為此,我們?yōu)槔夏甏x擇了UseConcMarkSweepGC 選擇了并發(fā)gc算法,也為新生代選擇了多線程的并行gc算法UseParNewGC。 3 設(shè)置新生代的內(nèi)存大小 java -server -Xmx5000m -Xms5000m -Xmn800m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC Xmn是新生代的內(nèi)存大小,包括(eden+ 2 survivor space)。這個(gè)參數(shù)設(shè)置直接影響系統(tǒng)的響應(yīng)速度。在java程序中new一個(gè)對(duì)象,首先是放在eden區(qū)域,eden滿了后,觸發(fā)gc,存活下來的對(duì)象被拷貝到survivor區(qū)。經(jīng)過若干次yong gc后,如果依然存活下來,就會(huì)進(jìn)入老年代。新生代設(shè)置大了,會(huì)導(dǎo)致一次yong gc的時(shí)間消耗大,設(shè)置小了,又會(huì)很快滿了,導(dǎo)致yong gc的頻率過高。新生代不宜設(shè)置過大,因?yàn)樾律罅?,老年代的?nèi)存就小了,老年代內(nèi)存小,會(huì)導(dǎo)致full gc發(fā)生的頻率變大。Xmn也沒有一個(gè)確切的算法,根據(jù)你自身的業(yè)務(wù)系統(tǒng)決定的。我在設(shè)置的游戲服務(wù)器的時(shí)候,一般采用模擬大量并發(fā)用戶的行為,調(diào)整Xmn的大小,同時(shí)監(jiān)控gc的時(shí)間和頻率,選擇一個(gè)合適的大小。下面我會(huì)提到怎么用工具來監(jiān)控gc。 4 設(shè)置一些額外的高級(jí)參數(shù) java -server -Xmx5000m -Xms5000m -Xmn800m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 使用CMS進(jìn)行老年代gc,會(huì)容易導(dǎo)致一些內(nèi)存碎片,導(dǎo)致內(nèi)存利用率降低,為此,加入 UseCMSCompactAtFullCollection 可以保證在full gc時(shí)進(jìn)行內(nèi)存壓縮,減少內(nèi)存碎片。CMSInitiatingOccupancyFraction=70 表示老年代內(nèi)存達(dá)到70%時(shí)觸發(fā)。這個(gè)參數(shù)要特別小心,設(shè)置得過小會(huì)導(dǎo)致full gc沒有完成,yong gc的對(duì)象遷移過來,導(dǎo)致整個(gè)老年代內(nèi)存都滿了 工具 § jstat 用來實(shí)時(shí)查看gc的狀態(tài), 用法:jstat -gcutil 進(jìn)程號(hào) 時(shí)間(毫秒)。結(jié)果如下: 里面列出每個(gè)區(qū)間的內(nèi)存大小,新生代gc的次數(shù)和時(shí)間,老年代gc的次數(shù)和時(shí)間。這里都能反映出你的JVM的運(yùn)行狀況 § jmap 用于查看java進(jìn)程的對(duì)象狀況 用法:jmap -histo:live 進(jìn)程id ??梢源蛴∶總€(gè)類的實(shí)例數(shù)量,內(nèi)存大小 用法:jmap -dump:format=b,file=log.bin 進(jìn)程id 這個(gè)命令特別有用,可以將jvm的整個(gè)內(nèi)存鏡像拷貝下來,用于分析每個(gè)對(duì)象占用的內(nèi)存狀況。當(dāng)你的java進(jìn)程崩潰了,用這個(gè)方法,可以分析出哪些對(duì)象是罪魁禍?zhǔn)?/font> § jstack 用于查看java進(jìn)程id的堆棧信息 用法:jstack 進(jìn)程id 這個(gè)工具對(duì)于查看死循環(huán)的線程很有效,可以直接找出是哪個(gè)線程在哪個(gè)方法內(nèi)死循環(huán)了 總結(jié) JVM的參數(shù)有很多,大部分我們都不需要去設(shè)置和優(yōu)化。如果你的程序沒有問題,就不要去折騰。如果你要優(yōu)化,一定要有相應(yīng)的測(cè)試流程來支撐。希望能與大家交流多一些JVM方面的優(yōu)化,尤其是實(shí)戰(zhàn)方面遇到的問題。我的郵件 ken@ (轉(zhuǎn)載本站文章請(qǐng)注明作者和出處 ken – www. ,請(qǐng)勿用于商業(yè)用途) 參考資料 § JVM參數(shù) http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html § JVM參數(shù)設(shè)置、分析 http://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html |
|