spark性能優(yōu)化四:Java虛擬機(jī)調(diào)優(yōu)

1、Java虛擬機(jī)垃圾回收調(diào)優(yōu)的背景

Spark雖然是scala開發(fā)的狂秘,但是其中也調(diào)用了很多的java api骇径,而且scala也是運(yùn)行在Java虛擬機(jī)中,所以spark是運(yùn)行在java虛擬機(jī)中的者春。

如果在持久化RDD的時(shí)候破衔,持久化了大量的數(shù)據(jù),那么Java虛擬機(jī)的垃圾回收就可能成為一個(gè)性能瓶頸钱烟。因?yàn)镴ava虛擬機(jī)會定期進(jìn)行垃圾回收晰筛,此時(shí)就會追蹤所有的java對象,并且在垃圾回收時(shí)拴袭,找到那些已經(jīng)不再使用的對象读第,然后清理舊的對象,來給新的對象騰出內(nèi)存空間拥刻。

垃圾回收的性能開銷怜瞒,是跟內(nèi)存中的對象的數(shù)量,成正比的。所以吴汪,對于垃圾回收的性能問題惠窄,首先要做的就是,使用更高效的數(shù)據(jù)結(jié)構(gòu)漾橙,如果array和string杆融;其次就在持久化RDD時(shí),使用序列化的持久化級別霜运,而且用Kryo序列化類庫脾歇,這樣,每個(gè)partition就只是一個(gè)對象——一個(gè)字節(jié)數(shù)組

2淘捡、監(jiān)測垃圾回收

我們可以對垃圾回收進(jìn)行監(jiān)測介劫,包括多久進(jìn)行一個(gè)垃圾回收,以及每次垃圾回收耗費(fèi)的時(shí)間案淋;只要在spark-submit腳本中座韵,增加一個(gè)配置既可,

--conf "spark.executor.extraJavaOptions=-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps"踢京。

注:這里打印出Java虛擬機(jī)的垃圾回收的相關(guān)信息誉碴,是輸出到worker上的日志中了

只是其中一種監(jiān)測方法,還可以通過SparkUI(4040端口)來觀察每個(gè)stage的垃圾回收的情況瓣距。

3黔帕、垃圾回收過程

Java堆空間被劃分成了兩塊空間,一個(gè)是年輕代蹈丸,一個(gè)是老年代成黄。年輕代放的是短時(shí)間存活的對象,老年代放的是長時(shí)間存活的對象逻杖,年輕代又被劃分為三塊空間奋岁,Eden、Survivor1荸百、Survivor2闻伶;

  • 首先,Eden區(qū)域和Survivor1區(qū)域用于存放對象够话,Survivor2區(qū)域備用蓝翰。創(chuàng)建的對象,首先放入Eden區(qū)域和Survivor1區(qū)域女嘲,如果Eden區(qū)域滿了畜份,那么就會觸發(fā)一次Minor GC(小型垃圾回收),進(jìn)行年輕代的垃圾回收——Eden和Survivor1區(qū)域中存活的對象欣尼,會被移動(dòng)到Survivor2區(qū)域中爆雹,然后Survivor1和Survivor2的角色調(diào)換,Survivor1變成了備用。

  • 其次顶别,如果一個(gè)對象,在年輕代中拒啰,撐過了多次垃圾回收驯绎,都沒有被回收掉,那么會被認(rèn)為是長時(shí)間存活的谋旦,此時(shí)就會被移入老年代剩失。此外,默認(rèn)eden册着、survior1拴孤、survior2的內(nèi)存比例是8:1:1,如果在將Eden和Survivor1中的存活對象甲捏,嘗試放入Survivor2中時(shí)演熟,發(fā)現(xiàn)Survivor2已經(jīng)滿了,那么就會直接放入老年代司顿,這時(shí)就會出現(xiàn)芒粹,短時(shí)間存活的對象,進(jìn)入老年代的問題大溜。如果老年代的空間滿了化漆,那么就會觸發(fā)Full GC,進(jìn)行老年代的垃圾回收操作钦奋。

如果你的JVM內(nèi)存不夠大的話座云,可能導(dǎo)致頻繁的年輕代內(nèi)存滿溢,頻繁的進(jìn)行minor gc付材。頻繁的minor gc會導(dǎo)致短時(shí)間內(nèi)朦拖,有些存活的對象,多次垃圾回收都沒有回收掉厌衔。會導(dǎo)致這種短聲明周期(其實(shí)不一定是要長期使用的)對象贞谓,年齡過大,垃圾回收次數(shù)太多還沒有回收到葵诈,跑到老年代裸弦。

老年代中,可能會因?yàn)閮?nèi)存不足作喘,囤積一大堆理疙,短生命周期的,本來應(yīng)該在年輕代中的泞坦,可能馬上就要被回收掉的對象窖贤。此時(shí),可能導(dǎo)致老年代頻繁滿溢。頻繁進(jìn)行full gc(全局/全面垃圾回收)赃梧。full gc就會去回收老年代中的對象滤蝠。full gc由于這個(gè)算法的設(shè)計(jì),是針對的是授嘀,老年代中的對象數(shù)量很少物咳,滿溢進(jìn)行full gc的頻率應(yīng)該很少,因此采取了不太復(fù)雜蹄皱,但是耗費(fèi)性能和時(shí)間的垃圾回收算法览闰。full gc很慢。

full gc / minor gc巷折,無論是快压鉴,還是慢,都會導(dǎo)致jvm的工作線程停止工作锻拘,就是說油吭,gc的時(shí)候,spark停止工作了署拟。

總結(jié)上鞠,內(nèi)存不充足的時(shí)候:

  • 1、頻繁minor gc芯丧,也會導(dǎo)致頻繁spark停止工作
  • 2芍阎、老年代囤積大量活躍對象(短生命周期的對象),導(dǎo)致頻繁full gc缨恒,full gc時(shí)間很長谴咸,短則數(shù)十秒,長則數(shù)分鐘骗露,甚至數(shù)小時(shí)岭佳。可能導(dǎo)致spark長時(shí)間停止工作萧锉。
  • 3珊随、嚴(yán)重影響咱們的spark的性能和運(yùn)行的速度。

4柿隙、Spark垃圾回收調(diào)優(yōu)之executor內(nèi)存

Spark中叶洞,垃圾回收調(diào)優(yōu)的目標(biāo)就是,只有真正長時(shí)間存活的對象禀崖,才能進(jìn)入老年代衩辟,短時(shí)間存活的對象,只能呆在年輕代波附,不能因?yàn)槟硞€(gè)Survivor區(qū)域空間不夠艺晴,在Minor GC時(shí)昼钻,就進(jìn)入了老年代,從而造成短時(shí)間存活的對象封寞,長期呆在老年代中占據(jù)了空間然评,從而導(dǎo)致頻繁Full GC。
Full GC時(shí)狈究,要回收大量的短時(shí)間存活的對象碗淌,導(dǎo)致Full GC速度緩慢。

如果在task執(zhí)行期間谦炒,發(fā)生了大量Full GC贯莺,那么說明风喇,年輕代的Eden區(qū)域給的空間不夠大宁改,此時(shí)可執(zhí)行一些操作來優(yōu)化垃圾回收行為:

  • 1、優(yōu)化executor內(nèi)存比例魂莫,降低cache操作的內(nèi)存占比
    對于Spark應(yīng)用的垃圾回收來說还蹲,最重要是就是調(diào)節(jié)RDD緩存占用的內(nèi)存空間,與算子執(zhí)行時(shí)創(chuàng)建的對象占用的內(nèi)存空間的比例耙考。默認(rèn)情況下谜喊,Spark使用每個(gè)executor 60%的內(nèi)存空間來緩存RDD,那么在task執(zhí)行期間創(chuàng)建的對象倦始,只有40%的內(nèi)存空間來存放斗遏。
    在這種情況下,很有可能因?yàn)槟愕膬?nèi)存空間的不足鞋邑,task創(chuàng)建的對象過多诵次,那么一旦發(fā)現(xiàn)40%的內(nèi)存空間不夠用了,就會觸發(fā)java虛擬機(jī)的垃圾回收操作枚碗,因此在極端情況下逾一,垃圾回收操作可能會被頻繁觸發(fā),導(dǎo)致spark頻繁的停止工作肮雨,性能影響會很大遵堵。
    在上述情況下,如果發(fā)現(xiàn)垃圾回收頻繁發(fā)生怨规,(可以通過spark UI來查看陌宿,可以看到stage的運(yùn)行情況,包括stage每個(gè)task的運(yùn)行時(shí)間波丰,gc時(shí)間等)那么就需要會那個(gè)比例進(jìn)行調(diào)優(yōu)限番,使用new SparkConf().set("spark.storage.memoryFraction", "0.5"),——spark.storage.memoryFraction呀舔,0.6 -> 0.5 -> 0.4 -> 0.2
    ——可以將RDD緩存占用空間的比例降低弥虐,從而給更多的空間讓task創(chuàng)建的對象進(jìn)行使用扩灯。
    因此,對于RDD持久化霜瘪,完全可以使用Kryo序列化珠插,加上降低其executor內(nèi)存占比的方式,來減少其內(nèi)存消耗颖对;給task提供更多的內(nèi)存捻撑,從而避免task的執(zhí)行頻繁觸發(fā)垃圾回收。

  • 2缤底、給Eden區(qū)域分配更大的空間顾患,使用-Xmn即可,通常建議給Eden區(qū)域个唧,預(yù)計(jì)大小的4/3江解;

  • 3、如果使用的是HDFS文件徙歼,那么很好估計(jì)Eden區(qū)域的大小犁河,如果每個(gè)executor有4個(gè)task,然后每個(gè)hdfs壓縮塊加壓縮后大小是3倍魄梯,此外每個(gè)HDFS塊的大小是64M桨螺,那么Eden區(qū)域的預(yù)計(jì)大小就是:4 * 3 * 64MB,然后通過-Xmn參數(shù)酿秸,將Eden區(qū)域大小設(shè)置為4 * 3 * 64 * 3/4

5灭翔、Spark垃圾回收調(diào)優(yōu)之executor堆外內(nèi)存

有時(shí)候,如果spark作業(yè)處理的數(shù)據(jù)量特別特別大辣苏,幾億數(shù)據(jù)量肝箱;然后spark作業(yè)一運(yùn)行,時(shí)不時(shí)的報(bào)錯(cuò)考润,shuffle file cannot find狭园,executor、task lost糊治,out of memory(內(nèi)存溢出)唱矛;

可能是說executor的堆外內(nèi)存不太夠用,導(dǎo)致executor在運(yùn)行的過程中井辜,可能會內(nèi)存溢出绎谦;然后可能導(dǎo)致后續(xù)的stage的task在運(yùn)行的時(shí)候,可能要從一些executor中去拉取shuffle map output文件粥脚,但是executor可能已經(jīng)掛掉了窃肠,關(guān)聯(lián)的block manager也沒有了;所以可能會報(bào)shuffle output file not found刷允;resubmitting task冤留;executor lost碧囊;spark作業(yè)徹底崩潰。

上述情況下纤怒,就可以去考慮調(diào)節(jié)一下executor的堆外內(nèi)存糯而。也許就可以避免報(bào)錯(cuò);此外泊窘,有時(shí)熄驼,堆外內(nèi)存調(diào)節(jié)的比較大的時(shí)候,對于性能來說烘豹,也會帶來一定的提升瓜贾。

比如在一個(gè)spark作業(yè)中,有兩個(gè)stage携悯,在作業(yè)運(yùn)行的時(shí)候祭芦,stage0的executor掛了,block manager也沒有了蚌卤;此時(shí)实束,stage1的executor的task奥秆,雖然通過Driver的MapOutputTrakcer獲取到了自己數(shù)據(jù)的地址逊彭;但是實(shí)際上去找對方的block manager獲取數(shù)據(jù)的時(shí)候,是獲取不到的构订,此時(shí)會在本機(jī)就會打印出log shuffle output file not found侮叮。。悼瘾。(使用
client—standalone client囊榜、yarn client—模式模式)
DAGScheduler resubmitting task時(shí),會一直會掛掉亥宿,反復(fù)掛掉幾次卸勺,反復(fù)報(bào)錯(cuò)幾次,這會導(dǎo)致整個(gè)spark作業(yè)崩潰了

調(diào)節(jié)方式:--conf spark.yarn.executor.memoryOverhead=2048
注意烫扼,這個(gè)針對的是基于yarn的提交模式曙求;
默認(rèn)情況下,這個(gè)堆外內(nèi)存上限大概是300多M映企;后來我們通常項(xiàng)目中悟狱,真正處理大數(shù)據(jù)的時(shí)候,這里都會出現(xiàn)問題堰氓,導(dǎo)致spark作業(yè)反復(fù)崩潰挤渐,無法運(yùn)行;此時(shí)就會去調(diào)節(jié)這個(gè)參數(shù)双絮,到至少1G(1024M)浴麻,甚至是2G得问、4G

通常這個(gè)參數(shù)調(diào)節(jié)上去以后,就會避免掉某些JVM OOM的異常問題软免,同時(shí)呢椭赋,會讓整體spark作業(yè)的性能,得到較大的提升或杠。

6哪怔、Executor gc引起的連接超時(shí)

Executor的task在執(zhí)行算子操作時(shí),優(yōu)先從本地關(guān)聯(lián)的BlockManager中獲取數(shù)據(jù)向抢,如果本地blockManger中沒有认境,那么會通過TransferService去遠(yuǎn)程連接其他節(jié)點(diǎn)上Executor的BlockManager去獲取。
如果此時(shí)挟鸠,正好碰到那個(gè)executor的JVM在垃圾回收叉信,此時(shí)就會沒有響應(yīng),無法建立網(wǎng)絡(luò)連接艘希,會卡住硼身,Spark默認(rèn)的的網(wǎng)絡(luò)連接超時(shí)時(shí)間是60s,如果60s都無法建立連接的話覆享,就宣告失敗佳遂。

之前碰到一種情況,偶爾撒顿,偶爾丑罪,偶爾!7锉凇吩屹!沒有規(guī)律!E《丁煤搜!某某file。一串file id唧席。uuid(dsfsfd-2342vs--sdf--sdfsd)擦盾。not found。file lost袱吆。
這種情況下厌衙,很有可能是有那份數(shù)據(jù)的executor在jvm gc。所以拉取數(shù)據(jù)的時(shí)候绞绒,建立不了連接婶希。然后超過默認(rèn)60s以后,直接宣告失敗蓬衡。
報(bào)錯(cuò)幾次喻杈,幾次都拉取不到數(shù)據(jù)的話彤枢,可能會導(dǎo)致spark作業(yè)的崩潰。也可能會導(dǎo)致DAGScheduler筒饰,反復(fù)提交幾次stage缴啡。TaskScheduler,反復(fù)提交幾次task瓷们。大大延長我們的spark作業(yè)的運(yùn)行時(shí)間业栅。

這時(shí)候可以考慮調(diào)節(jié)連接的超時(shí)時(shí)長。
--conf spark.core.connection.ack.wait.timeout=300
調(diào)節(jié)這個(gè)值比較大以后谬晕,通常來說碘裕,可以避免部分的偶爾出現(xiàn)的某某文件拉取失敗,某某文件lost掉了攒钳。帮孔。。

在真正處理大數(shù)據(jù)(不是幾千萬數(shù)據(jù)量不撑、幾百萬數(shù)據(jù)量)文兢,幾億,幾十億焕檬,幾百億的時(shí)候姆坚。很容易碰到executor堆外內(nèi)存,以及gc引起的連接超時(shí)的問題揩页。file not found旷偿,executor lost烹俗,task lost爆侣。
調(diào)節(jié)上面兩個(gè)參數(shù),還是很有幫助的幢妄。

/usr/local/spark/bin/spark-submit \
--class com.ibeifeng.sparkstudy.WordCount \
--num-executors 80 \
--driver-memory 6g \
--executor-memory 6g \
--executor-cores 3 \
--master yarn-cluster \
--queue root.default \
--conf spark.yarn.executor.memoryOverhead=2048 \
--conf spark.core.connection.ack.wait.timeout=300 \
/usr/local/spark/spark.jar \

7兔仰、總結(jié)

根據(jù)經(jīng)驗(yàn)來看,對于垃圾回收的調(diào)優(yōu)蕉鸳,盡量是調(diào)節(jié)executor內(nèi)存的比例就可以了乎赴,因?yàn)閖vm的調(diào)優(yōu)是非常復(fù)雜和敏感的,除非到了萬不得已的地方潮尝,同時(shí)榕吼,自己對jvm相關(guān)的技術(shù)很了解,然后才進(jìn)行Eden區(qū)域的調(diào)節(jié)

注:一些高級的參數(shù)
-XX:SurvivorRatio=4:如果值為4勉失,那么就是兩個(gè)Survivor跟Eden的比例是2:4羹蚣,也就是說每個(gè)Survivor占據(jù)的年輕代比例是1/6,所以乱凿,也可以嘗試調(diào)大Survivor區(qū)域的大型缢亍咽弦;
-XX:NewRatio=4:調(diào)節(jié)新生代和老年代的比例

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市胁出,隨后出現(xiàn)的幾起案子型型,更是在濱河造成了極大的恐慌,老刑警劉巖全蝶,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闹蒜,死亡現(xiàn)場離奇詭異,居然都是意外死亡抑淫,警方通過查閱死者的電腦和手機(jī)嫂用,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丈冬,“玉大人嘱函,你說我怎么就攤上這事」∪铮” “怎么了往弓?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蓄氧。 經(jīng)常有香客問我函似,道長,這世上最難降的妖魔是什么喉童? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任撇寞,我火速辦了婚禮,結(jié)果婚禮上堂氯,老公的妹妹穿的比我還像新娘蔑担。我一直安慰自己,他們只是感情好咽白,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布啤握。 她就那樣靜靜地躺著,像睡著了一般晶框。 火紅的嫁衣襯著肌膚如雪排抬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天授段,我揣著相機(jī)與錄音蹲蒲,去河邊找鬼。 笑死侵贵,一個(gè)胖子當(dāng)著我的面吹牛届搁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼咖祭,長吁一口氣:“原來是場噩夢啊……” “哼掩宜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起么翰,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤牺汤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后浩嫌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體檐迟,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年码耐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了追迟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡骚腥,死狀恐怖敦间,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情束铭,我是刑警寧澤廓块,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站契沫,受9級特大地震影響带猴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜懈万,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一拴清、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧会通,春花似錦口予、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至驾凶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間掷酗,已是汗流浹背调违。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留泻轰,地道東北人技肩。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親虚婿。 傳聞我的和親對象是個(gè)殘疾皇子旋奢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

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