性能調優java
- 常規性能調優:分配資源、並行度。。。等
- JVM調優(Java虛擬機):JVM相關的參數,一般狀況下,若是你的硬件配置、基礎的JVM的配置,均可以的話,JVM一般不會形成太嚴重的性能問題;反而更多的是,在troubleshooting中,JVM佔了很重要的地位;JVM形成線上的spark做業的運行報錯,甚至失敗(好比OOM)。
- shuffle調優(至關重要):spark在執行groupByKey、reduceByKey等操做時的,shuffle環節的調優。這個很重要。shuffle調優,其實對spark做業的性能的影響,是至關之高!!!經驗:在spark做業的運行過程當中,只要一牽扯到有shuffle的操做,基本上shuffle操做的性能消耗,要佔到整個spark做業的50%~90%。10%用來運行map等操做,90%耗費在shuffle操做。
- spark操做調優(spark算子調優,比較重要):有些算子的性能,是比其餘一些算子的性能要高的。foreachPartition替代foreach。
若是一旦遇到合適的狀況,效果仍是不錯的。算法
一、分配資源、並行度、RDD架構與緩存
二、shuffle調優
三、spark算子調優
四、JVM調優、廣播大變量。。。數據庫JVM調優原理概述。api
JVM調優裏面全部官方都推薦來下降cache操做佔比緩存
- 理論基礎:spark是用scala開發的。你們不要覺得scala就跟java一點關係都沒有了,這是一個很常見的錯誤。spark的scala代碼調用了不少java api。scala也是運行在java虛擬機中的。spark是運行在java虛擬機中的。java虛擬機可能會產生什麼樣的問題:內存不足??!!咱們的RDD的緩存、task運行定義的算子函數,可能會建立不少對象。均可能會佔用大量內存,沒搞好的話,可能致使JVM出問題。
- 堆內存:
- 存放咱們建立的一些對象,堆內存分爲年輕帶young generation和老年帶old generation,年輕帶內部又分爲三塊,Eden區域比較大,兩個survivor區域比較小存活區域咱們在spark task執行算子函數(咱們本身寫的針對RDD的操做),可能會建立不少對象,這些對象,都是要放入JVM年輕代中的。每一次放對象的時候,都是放入eden區域,和其中一個survivor區域;另一個survivor區域是空閒的。當eden區域和一個survivor區域放滿了之後(spark運行過程當中,產生的對象實在太多了),就會觸發minor gc,小型垃圾回收。垃圾回收器gc會把再也不使用的對象,從內存中清空,給後面新建立的對象騰出來點兒地方。
- 清理掉了再也不使用的對象以後,那麼也會將存活下來的對象(還要繼續使用的),放入以前空閒的那一個survivor區域中。這裏可能會出現一個問題。默認eden、survior1和survivor2的內存佔比是8:1:1。問題是,若是存活下來的對象是1.5,一個survivor區域放不下。此時就可能經過JVM的擔保機制(不一樣JVM版本可能對應的行爲),將多餘的對象,直接放入老年代了。
- 若是你的JVM內存不夠大的話,可能致使頻繁的年輕代內存滿溢,頻繁的進行minor gc。頻繁的minor gc會致使短期內,有些存活的對象,屢次垃圾回收都沒有回收掉。就是那些一直在用的又不能被釋放的就頻繁的倒來倒去!會致使這種短聲明週期(其實不必定是要長期使用的)對象,每回收一次,年齡長一歲!年齡過大,垃圾回收次數太多尚未回收到,跑到老年代。
- 說白了就是短聲明週期對象卻跑到老年代裏面去了!!!原本是短週期的,結果倒來倒去跑到老年代裏面去了,理想狀況下,老年代都是放一些生命週期很長的對象,數量應該是不多的。好比數據庫鏈接池,數據庫鏈接池原本就不多。
- 簡而言之,老年代中,可能會由於內存不足,囤積一大堆,短生命週期的,原本應該在年輕代中的,可能立刻就要被回收掉的對象。此時,可能致使老年代頻繁滿溢。頻繁進行full gc(全局/全面垃圾回收)。full gc就會去回收老年代中的對象。full gc因爲這個算法的設計,是針對的是,老年代中的對象數量不多,滿溢進行full gc的頻率應該不多,所以採起了不太複雜,可是耗費性能和時間的垃圾回收算法。full gc很慢。
- full gc / minor gc,不管是快,仍是慢,都會致使jvm的工做線程中止工做,stop the world。簡而言之,就是說,gc的時候,spark中止工做了。等着垃圾回收結束。
- 內存不充足的時候,問題:
- 頻繁minor gc,也會致使頻繁spark中止工做;
- 老年代囤積大量活躍對象(短生命週期的對象),致使頻繁full gc,full gc時間很長,短則數十秒,長則數分鐘,甚至數小時。可能致使spark長時間中止工做;
- 嚴重影響我們的spark的性能和運行的速度。
如何解決?架構
spark.storage.memoryFraction,0.6 -> 0.5 -> 0.4 -> 0.2
你們能夠本身去調,而後觀察spark做業的運行統計!!!而後看看總體運行時間有沒有改善!gc是否頻繁,gc時間等!上述比例均可以調!根據不一樣需求來作!jvm
.set("spark.storage.memoryFraction", "0.5")