Java虛擬機垃圾回收調優

      GC對性能的影響在於,如果內存中數據量比較大的話,那麼可能會造成GC頻繁的發生,另外如果要回收的數據量特別大,那麼會導致GC的速度也比較慢。gc線程工作時,會讓程序中的task線程暫停工作,那麼整個應用程序的性能就會大打折扣。

       對於Spark應用程序可以從以下幾個方面來優化。

       1、優化executor內存比例

       對於垃圾回收來說,最重要的就是調節RDD緩存佔用的內存空間,與算子執行時創建對象佔用的內存比例。默認情況下,Spark使用每個executor 60%的內存空間來緩存RDD,那麼task執行期間創建的對象,只有40%的內存空間來存放。

       這種情況下,很有可能因爲內存空間不足,task創建的對象過大,一旦發現40%的內存空間不夠用了,就會觸發虛擬機的垃圾回收操作,頻繁的GC會極大降低程序的整體性能。

        這個時候就需要對這個比例進行調優,使用SparkContext.set("spark.storage.memoryFraction","0.5")即可,這樣就提高了創建對象所用的內存。

        對於RDD的緩存,可以用Kryo序列化,加上降低其executor內存佔比方式,來減少其內存消耗。給task提供更多的內存,從而避免task的執行頻繁觸發GC。

      

        2、高級垃圾回收調優

        Java堆空間被分成兩塊空間,一個是年輕代,一個是老年代。年輕代放的是短時間存活的對象,老年代放的是長時間存活的對象。年輕代又劃分成了三塊空間,Eden、Survivor1、Survivor2。

        創建對象時,首先放入Eden區域和Survivor1區域,如果Eden區域滿了,那麼就會觸發一次MinorGC,進行年輕代垃圾回收。此區域中存活的對象會被移到Survivor2區域中,然後Survivor1和Survivor2角色調換,Survivor1成了備用。

        如果一個對象,在年輕代中,撐過了多次垃圾回收,都沒有被回收掉,那麼會被認爲是長時間存活的,此時就會被移入老年代。此外,如果在將Eden和Survivor1的存活對象,嘗試放到Survivor2中時,發現Survivor1滿了,那麼會直接放入老年代。此時很快就會將老年代內存撐滿,從而發生full gc。full gc要回收大量的短時間存活的對象,會導致速度很緩慢。此時可以執行一些操作來優化垃圾回收行爲:

         1)給年輕代分配更大的空間,使用-XX:NewRatio=n(n爲年輕代與老年代的比值)

         2)給Eden區域分配更大的內存,使用-XX:SurvivorRatio=n(n爲年輕代中Eden區與Survivor區的大小比值)

         3)-Xmn=20g,這個參數可以直接指定年輕代內存大小

         4)使用吞吐量優先的並行收集器。

              -XX:+UseParallelGC:選擇年輕代垃圾收集器爲並行收集器,即MinorGC

              -XX:ParallelGCThreads:配置並行收集器的線程數,有多少處理器就多少線程

              -XX:+UseParallelOldGC:配置年老代垃圾收集方式爲並行收集

    


      

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