記一次生產(chǎn)事故—JIT編譯與CPU使用率飆升

一個隱藏比較深的問題爵赵。項目使用grpc完成遠程調(diào)用扛或,但是grpc定義的pd文件,由于message中參數(shù)過多瓢颅,達到190多個恩尾,在pb的該message某次新增一個字段后。項目的CPU使用率直接由10%飆升到70%挽懦。

1. 基礎(chǔ)知識

1.1 什么叫做JIT

在計算機技術(shù)中翰意,即時編譯(just-in-time,縮寫JIT;又譯及時編譯冀偶、實時編譯)醒第,也被稱為動態(tài)編譯或者運行時編譯,是一種執(zhí)行計算機代碼的方法进鸠,這種方法涉及在程序執(zhí)行過程中(在執(zhí)行期)而不是執(zhí)行之前進行編譯稠曼。

1.2 JIT工作原理

在字節(jié)碼編譯的系統(tǒng)中,源代碼被轉(zhuǎn)換為稱為字節(jié)碼的中間表示形式客年。字節(jié)碼不是任何特定計算機的機器代碼霞幅,可以在計算機體系結(jié)構(gòu)之間移植(即JAVA的跨平臺性)。然后可以在虛擬機上解釋或者運行字節(jié)碼量瓜、JIT編譯器在許多(或全部司恳、很少)部分讀取字節(jié)碼,并將他們動態(tài)的編譯成機器代碼榔至,以便程序更快速運行抵赢。這可以針對每個文件、每個函數(shù)甚至任何任意代碼片段進行編譯唧取;代碼可以在即將執(zhí)行時進行編譯(因此稱為“即時”)铅鲤,然后緩存并在以后重用,無需重新編譯枫弟。

缺省情況下邢享,啟用JIT編譯器。在編譯方法時淡诗,JVM直接調(diào)用該方法的已編譯代碼骇塘,而不是對代碼進行解釋。理論上韩容,如果編譯不需要占用處理器時間和內(nèi)存款违,那么編譯每個方法都可能使JAVA程序速度接近于本機應(yīng)用程序的速度。

JVM流程.png

圖片來源:如何通俗易懂地介紹「即時編譯」(JIT)

疑問群凶?為什么JVM里既有compiler插爹,也有interpreter(解釋器)?

JVM在解釋器之外引入了即時(Just In Time)編譯器:當(dāng)程序運行時请梢,解釋器首先發(fā)揮作用赠尾,代碼可以直接執(zhí)行。隨著時間推移毅弧,即時編譯器逐漸發(fā)揮作用气嫁,把越來越多的代碼編譯優(yōu)化成本地代碼,來獲取更高的執(zhí)行效率够坐。解釋器這時可以作為編譯運行的降級手段寸宵,在一些不可靠的編譯優(yōu)化出現(xiàn)問題時崖面,再切換回解釋執(zhí)行,保證程序可以正常運行邓馒。

1.3 JIT編譯是在項目啟動時編譯的嗎嘶朱?

不是!JIT編譯不需要占用處理器時間和內(nèi)存光酣。在JVM首次啟動時疏遏,將調(diào)用數(shù)千種方法。即使程序最終實現(xiàn)了較高的峰值性能救军,編譯所有這些方法也會對啟動時間產(chǎn)生顯著影響财异。實際上,第一次調(diào)用方法時不會對方法進行編譯唱遭。對于每個方法戳寸,JVM都會保留一個調(diào)用計數(shù),以預(yù)定義的編譯閾值開始拷泽,并在每次調(diào)用方法時遞減疫鹊。在調(diào)用計數(shù)達到零時,將觸發(fā)方法的即時編譯司致。因此拆吆,在JVM啟動后將立即編譯常用方法,而較長時間(或者根本不編譯)不常用的方法脂矫。JIT編譯閾值幫助JVM快速啟動并且還可以提高性能枣耀。選擇閾值以在啟動時與長期性能之間實現(xiàn)最佳平衡。

image.png

圖片來源:基本功 | Java即時編譯器原理解析及實踐

為了提升執(zhí)行速度庭再,Hotspot JVM采用了JIT compile技術(shù)捞奕,JIT編譯器將運行頻率很高的字節(jié)碼(熱點代碼)直接編譯為機器碼執(zhí)行以提高性能。

1.4 JIT編譯與靜態(tài)編譯

常見的編譯型語言如C++拄轻,通常會把代碼直接編譯成CPU所能理解的機器碼來運行颅围。而Java為了實現(xiàn)“一次編譯,處處運行”的特性恨搓,把編譯的過程分成兩部分谷浅,首先它會先由javac編譯成通用的中間形式——字節(jié)碼,然后再由解釋器逐條將字節(jié)碼解釋為機器碼來執(zhí)行奶卓。所以在性能上,Java通常不如C++這類編譯型語言撼玄。

為了優(yōu)化Java的性能 夺姑,JVM在解釋器之外引入了即時(Just In Time)編譯器:當(dāng)程序運行時,解釋器首先發(fā)揮作用掌猛,代碼可以直接執(zhí)行盏浙。隨著時間推移眉睹,即時編譯器逐漸發(fā)揮作用,把越來越多的代碼編譯優(yōu)化成本地代碼废膘,來獲取更高的執(zhí)行效率竹海。解釋器這時可以作為編譯運行的降級手段蚕礼,在一些不可靠的編譯優(yōu)化出現(xiàn)問題時霎匈,再切換回解釋執(zhí)行,保證程序可以正常運行寄悯。

即時編譯器極大地提高了Java程序的運行速度灌闺,而且跟靜態(tài)編譯相比艰争,JIT(即時編譯器)可以選擇性地編譯熱點代碼,省去了很多編譯時間桂对,也節(jié)省很多的空間甩卓。目前,即時編譯器已經(jīng)非常成熟了蕉斜,在性能層面甚至可以和編譯型語言相比逾柿。不過在這個領(lǐng)域,大家依然在不斷探索如何結(jié)合不同的編譯方式宅此,使用更加智能的手段來提升程序的運行速度机错。

2. JIT編譯與CPU使用率飆升

上面說到JIT編譯,那么他和CPU使用率飆升有什么關(guān)系呢诽凌?

上面說到毡熏,熱點代碼會被直接編譯成機器碼執(zhí)行來提高性能,但是考慮這樣一個場景:熱點代碼每次調(diào)用時均逐條解釋(Interpreter)侣诵,是不是需要消耗CPU資源痢法?

那么您又得好奇了,JVM不是采用了JIT技術(shù)了嗎杜顺,為啥熱點代碼不會直接編譯成機器碼執(zhí)行财搁?

2.1 大方法默認關(guān)閉JIT編譯

上面說到,JVM是默認開啟JIT編譯器躬络,但是存在一個參數(shù)尖奔,若一個方法中字節(jié)碼大小超過8000字節(jié),那么就不允許被JIT編譯穷当,而8000這個閾值在產(chǎn)品版的HotSpot里無法被調(diào)整提茁。

關(guān)鍵詞:

-XX:+DontCompileHugeMethods
-XX:HugeMethodLimit=8000

解決方案:可以通過JVM參數(shù):-XX:-DontCompileHugeMethods來允許大方法被JIT編譯。

但是這種方式存在風(fēng)險馁菜,會導(dǎo)致所有的方法都有可能編譯成字節(jié)碼茴扁,但是一旦CodeCache滿了,后續(xù)的方法都無法編譯成字節(jié)碼汪疮,這種方法是存在一定風(fēng)險的峭火。

2.2 查看方法占用的字節(jié)

可以下載:jclasslib Bytecode viewer插件毁习。

使用方法:IDEA字節(jié)碼學(xué)習(xí)查看神器jclasslib bytecode viewer介紹

2.3 觸發(fā)場景以及解決方案

測試案例——Java中一個方法字節(jié)碼的長度為什么會影響程序并發(fā)下的性能?

在實際工作中卖丸,一個方法很少能超過8000字節(jié)纺且,但是自動生成的方法便存在這種風(fēng)險。例如本次事故稍浆,就是grpc的pb文件中载碌,一個message{}中的屬性字段太多導(dǎo)致的。

針對grpc的這種場景:可以增加一個嵌套的message字段粹湃,新增的字段都放在這個嵌套結(jié)構(gòu)下恐仑。可以解決這種業(yè)務(wù)場景为鳄。

參考資料

JIT 編譯器

如何通俗易懂地介紹「即時編譯」(JIT)

IDEA字節(jié)碼學(xué)習(xí)查看神器jclasslib bytecode viewer介紹

Java中一個方法字節(jié)碼的長度為什么會影響程序并發(fā)下的性能裳仆?

基本功 | Java即時編譯器原理解析及實踐

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市孤钦,隨后出現(xiàn)的幾起案子歧斟,更是在濱河造成了極大的恐慌,老刑警劉巖偏形,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件静袖,死亡現(xiàn)場離奇詭異,居然都是意外死亡俊扭,警方通過查閱死者的電腦和手機队橙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來萨惑,“玉大人捐康,你說我怎么就攤上這事∮拱” “怎么了解总?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長姐仅。 經(jīng)常有香客問我花枫,道長,這世上最難降的妖魔是什么掏膏? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任劳翰,我火速辦了婚禮,結(jié)果婚禮上馒疹,老公的妹妹穿的比我還像新娘磕道。我一直安慰自己,他們只是感情好行冰,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布溺蕉。 她就那樣靜靜地躺著,像睡著了一般悼做。 火紅的嫁衣襯著肌膚如雪疯特。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天肛走,我揣著相機與錄音漓雅,去河邊找鬼。 笑死朽色,一個胖子當(dāng)著我的面吹牛邻吞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播葫男,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼抱冷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了梢褐?” 一聲冷哼從身側(cè)響起旺遮,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盈咳,沒想到半個月后耿眉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡鱼响,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年鸣剪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丈积。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡筐骇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出桶癣,到底是詐尸還是另有隱情拥褂,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布牙寞,位于F島的核電站饺鹃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏间雀。R本人自食惡果不足惜悔详,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惹挟。 院中可真熱鬧茄螃,春花似錦、人聲如沸连锯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拼弃,卻和暖如春夏伊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吻氧。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工溺忧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盯孙。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓鲁森,卻偏偏與公主長得像,于是被迫代替她去往敵國和親振惰。 傳聞我的和親對象是個殘疾皇子歌溉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容