某天腦洞大開,把懷疑的目光投向了在后臺(tái)運(yùn)行日志收集程序Flume,發(fā)現(xiàn)它的GC運(yùn)行得比較狂野,于是對(duì)它的GC線程數(shù)做了限制: 修改前:15分鐘內(nèi), 大于30ms的業(yè)務(wù)調(diào)用173次, 大于50ms的23次
那這個(gè)新升級(jí)的監(jiān)控系統(tǒng),又是怎么影響到主應(yīng)用的呢?找出它與應(yīng)用有交互的部分,原來對(duì)于JVM的各種線程數(shù)信息,堆內(nèi)存各代的信息,每拿一個(gè)數(shù)據(jù)都會(huì)啟動(dòng)一次JMX Client,所以每分鐘都有一秒要連拿7個(gè)數(shù)據(jù),啟動(dòng)7個(gè)JMX Client。 改進(jìn)方法很簡單,我們自己定制了一下JMX Client,將7個(gè)數(shù)據(jù)合并在一個(gè)命令里獲得,另外定制了一下JMX Client的JVM參數(shù),將它啟動(dòng)的動(dòng)靜盡量減少。
一、啟動(dòng)快速,動(dòng)靜小。
在它們運(yùn)行時(shí),跑jps -v ,結(jié)果發(fā)現(xiàn)通通只有一個(gè)-Xms8m 。 還不死心,又去翻源碼,JDK7在 Makefile.launcher,JDK8在CompileLaunchers.gmk,結(jié)果發(fā)現(xiàn)全部8M,通通8M,再?zèng)]別的參數(shù)了。 有同學(xué)又從久遠(yuǎn)的記憶中想起一個(gè)-client,感覺也是比較弱氣的選項(xiàng),但在這個(gè)多核的64位Linux服務(wù)器上是根本無效的,一定是-server,必須是-server。
各種吃內(nèi)存 各種后臺(tái)線程 JIT時(shí)CPU表現(xiàn)狂野 GC時(shí)CPU表現(xiàn)狂野 那我們就從這幾個(gè)方面著手。 在開始折騰前,先準(zhǔn)備好測(cè)試手段: 首先,給工具腳本配上GC 日志參數(shù),在GC日志里就能看到實(shí)際啟動(dòng)參數(shù),GC紀(jì)錄,以及運(yùn)行結(jié)束時(shí)內(nèi)存各代的占用。 -Xloggc:gc.log -XX: PrintGCDetails -XX: PrintGCDateStamps -XX: PrintGCApplicationStoppedTime 其次,長期跑一個(gè) pidstat -l 1| grep xxx ,緊密監(jiān)控進(jìn)程的CPU消耗。 最后,jstack看線程。
6.2 設(shè)定編譯級(jí)別 但編譯本身就需要CPU,也需要額外的編譯線程。 如果腳本只簡單的跑一次,比如vjtools里的vjmxcli,建議就不要進(jìn)行JIT編譯了,編譯完了也用不上,直接解釋執(zhí)行就好。禁止它:-Djava.compiler=NONE 如果腳本用于密集計(jì)算,比如vjtools里的vjmap,則建議打開多層編譯,一開始就對(duì)運(yùn)行到的方法進(jìn)行靜態(tài)編譯,不用等方法被調(diào)用1萬次。多層編譯在JDK8默認(rèn)打開,顯式打開:-XX: TieredCompilation。 但打開多層編譯也會(huì)導(dǎo)致程序運(yùn)行初期有較多的編譯任務(wù),吃比較多的CPU,可以顯式關(guān)掉多層編譯 -XX:-TieredCompilation來對(duì)比一下,綜合其帶來的性能提升,腳本的運(yùn)行時(shí)間的長短,以及額外的CPU支出來綜合評(píng)價(jià)。 6.3 編譯線程的設(shè)定 6.4 未來黑科技-AOT 看各位大大炫,但我還沒玩過。
如果依然想使用并行算法,就一定要設(shè)置GC線程數(shù),在24核機(jī)器上YGC和CMS GC的線程數(shù)默認(rèn)分別是18和5,為了避免成為惡鄰A君??稍O(shè)為: -XX:ParallelGCThreads=4 -XX:ConcGCThreads=2
一,默認(rèn)的JVM初始內(nèi)存大小,在大內(nèi)存的服務(wù)器上會(huì)比較大,必須設(shè)置。 二,-Xms 與 -Xmx 不等時(shí), 自動(dòng)擴(kuò)張并沒有想象中那么智能和合理。 三、新生代默認(rèn)只有1/3堆大小,而在腳本看來新生代才是大頭。 建議根據(jù)GC日志的結(jié)果,完整設(shè)置-Xms 和 -Xmx,并用-Xmn(新生代占大頭) 或-XX:NewRatio=1(一半半) 來設(shè)置新生代大小。 其次,每條線程的內(nèi)存,從默認(rèn)1M回到256k: -xss256k 其他永久代,CodeCache的初始值還算合理,沒看到特別浪費(fèi)的情況不用管。
|
|
|