Spark性能調優---JVM調優之原理概述及降低cache操作的內存佔比

一、原理概述

①理論

Spark是用Scala開發的。Spark的Scala代碼調用了很多java api。Scala也是運行在JVM中的,所以Spark也是運行在JVM中的。

②JVM可能會產生什麼樣的問題?

內存不足——RDD的緩存、task運行定義的算子函數,可能會創建很多對象,佔用大量的內存。處理不當,可能導致JVM出問題。

③堆內存

  1. 作用:存放項目中創建的對象。
  2. 劃分:新生代(young generation,Eden區域+survivor區域1+survivor區域2,比例8:1:1),老年代(old generation)

④GC(垃圾回收)

每次創建出來的對象,都會放到Eden區域和survivor區域1中,另外一個survivor區域空閒。

由於spark作業產生的對象過多,當Eden區域和survivor區域放滿之後,就會觸發minor gc(初代回收)。把不再使用的對象從內存中清理出去,給後面對象的創建騰出空間。

清理掉了不再使用的對象之後,那些存活下來(還需要繼續使用)的對象,放入之前空閒的survivor區域2中。當survivor區域2滿了放不下,JVM會通過擔保機制機制將多餘的對象直接放到老年代中。

如果JVM內存不夠大,可能導致頻繁的新生代內存溢出,頻繁的minor gc。頻繁的minor gc會導致短時間內,有些存活下來的對象,經過多次垃圾回收都沒有回收掉,導致這種生命週期短(不一定會長期使用)的對象,年齡過大,進入老年代。

老年代中存在過多的短生命週期的、本該在新生代中可能馬上要被回收的對象,導致內存不足,頻繁內存滿溢,頻繁進行full gc(老年代回收)。full gc會回收老年代中的對象。由於老年代中的對象數量少,滿溢進行的full gc頻率本應該很少,所以回收算法很簡單,但是耗費性能和時間。——full gc很耗時間。

full gc/minor gc,無論快慢,都會導致JVM工作線程停止工作,spark作業會暫停,等待垃圾回收完成之後繼續工作。

⑤總結---內存不足導致的問題

  1. 頻繁minor gc,導致spark頻繁停止工作
  2. 老年代囤積大量活躍對象(短生命週期的對象),導致頻繁full gc,full gc時間很長,短則數十秒,長則數十分鐘,甚至數小時,導致spark長時間停止作業
  3. 嚴重影響spark作業的性能和運行的速度

二、降低cache操作的內存佔比

spark中,堆內存被劃分爲兩塊,一塊專門用來給RDD的cache、persist操作進行數據緩存使用;一塊用來給spark算子函數的運行使用,存放函數自己創建的對象。

默認情況下,給RDD cache操作的內存佔比是0.6,但是可能cache真正需要使用的內存不需要這麼多,而存儲spark算子函數創建對象需要大量的內存,這個時候可以調節這個參數,比如0.5、0.3、0.2等等。

用yarn運行spark的時候,通過yarn頁面可以查看spark作業的運行統計,一層一層點進去,可以看到每個stage的運行情況,包括每個task的運行時間、gc時間等。根據情況,如果gc頻繁,時間太長,可以適當地調整這個比例,反覆測試,直到調整到一個合適的比例。

在spark的代碼中設置示例:SparkConf.set("spark.storage.memoryFraction","0.6")

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章