天天看點

Spark廣播變量及GC調優

最新在工作中,需要在廣告中過濾黑名單,具體業務鑒于保密,暫不詳細闡述,本文想要說的是本次應用過程中使用Spark廣播變量及使用GC調優解決該問題的要點,有用到的夥伴可以參考

正常spark日志解析中加入黑名單解析

根據前期調研檢視,黑名單一類25萬+,3.86MB,黑名單二類106萬+,46.3MB,理論上完全可以将其封裝,采用spark廣播變量的方式廣播到每一個節點處理

但是實際在測試中,遇到一些問題,總結一下      

正常一個小時日志解析參數

--num-executors 10 --driver-memory 4g --executor-memory 30g --executor-cores 4 ,解析時間6~7min,接下來按照上述解析流程做了以下測試        

- 測試一、将兩種黑名單廣播出去解析之後,多次測試均超過1h無果,将任務kill掉

- 測試二、将兩種黑名單廣播出去解析之後,加大executors數和executor-memory,多次測試均超過1h無果,将任務kill掉

- 測試三、将兩種黑名單廣播出去解析之後,加大executors數和executor-memory,将預設GC垃圾回收器換成G1,G1屬于并行化垃圾回收器,超過50個task表現比較優秀,多次測試均超過1h無果,将任務kill掉

```

--conf spark.driver.extraJavaOptions="-XX:PermSize=256m -XX:MaxPermSize=256m -XX:+UseG1GC -XX:+PrintFlagsFinal \

-XX:+PrintReferenceGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintAdaptiveSizePolicy \

-XX:+UnlockDiagnosticVMOptions -XX:+G1SummarizeConcMark" \

```

- 測試四、将兩種黑名單廣播出去解析之後,加大executors數和executor-memory,将預設GC垃圾回收器換成G1,并且加大垃圾回收線程,多次測試均超過1h無果,将任務kill掉

```

--conf spark.driver.extraJavaOptions="-XX:PermSize=256m -XX:MaxPermSize=256m -XX:+UseG1GC -XX:+PrintFlagsFinal \

-XX:+PrintReferenceGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintAdaptiveSizePolicy \

-XX:+UnlockDiagnosticVMOptions -XX:+G1SummarizeConcMark -XX:InitiatingHeapOccupancyPercent=35 -XX:ConcGCThreads=20" \

```

- 測試五、問題還應該回歸到代碼中尋求解決思路,當時廣播的時候,資料加載到記憶體,把list廣播出去,後續解析使用list.contains,後來想到list和map在這個方法上性能應該不一樣,ArrayList使用的是數組來存儲元素,而HashMap使用哈希表來存儲元素,檢視源碼,list底層是數組,每調用一次contains方法,要周遊一次資料,通過index實作,時間複雜度O (n2),但是在HashMap,key被存儲到hash表中,查找時是在hash表上進行查找,時間複雜度幾乎是O (1),經過測試,果不其然,解析完,用時7min,以後大家如有用到,需注意,list的性能在千以下還可以,在10萬,100萬級别,比對的性能會大大縮小,性能比map差20倍不止,至此驗證了黑名單解析可以采用spark廣播的方式。

list contains通過調用自己的indexof實作,indexof源碼如下   

```

public int indexOf(Object o) {

        if (o == null) {

            for (int i = 0; i < size; i++)

                if (elementData[i]==null)

                    return i;

        } else {

            for (int i = 0; i < size; i++)

                if (o.equals(elementData[i]))

                    return i;

        }

        return -1;

    }

```

當然還可以在impala中使用join的方式解決該問題,impala預設采用hashjoin方式,非nextLoop算法,此處不再熬述。

後續有時間将GC的測試過程貼圖,最近較忙

繼續閱讀