標籤:

spark2.1 NIO_BUFFER_LIMIT常量定義的作用?

Spark的2.1的MessageWithHeader.java類中定義了下面的常量:

NIO_BUFFER_LIMIT = 256 * 1024

複製的buffer大小超過這個limit會分好幾次複製,這個宏定義的意義在哪裡?提升了性能嗎?


謝邀。我正好review了這個pull request。

NIO_BUFFER_LIMIT是用來控制每次寫ByteBuffer時的最大長度。當Spark調用JDK的API去寫ByteBuffer時,因為這個不是DirectByteBuffer,所以底層的IOUtils會去創建(也可能直接從內部的pool中取出來)DirectByteBuffer,然後把Spark要寫的ByteBuffer拷貝到這個DirectByteBuffer中,最後用native API去寫這個DirectByteBuffer。如果要寫的ByteBuffer比較大,超過當前系統可用的buffer大小,這個寫入需要進行多次。

在沒有加入NIO_BUFFER_LIMIT之前,每次寫都要拷貝整個ByteBuffer。假設我們要寫入1MB的ByteBuffer,而系統自身的buffer只有256KB,那麼需要寫4次,但是由於每次都拷貝ByteBuffer中剩餘的數據,總共要拷貝2.5MB(1MB + 768KB + 512KB + 256KB)的數據。而有了NIO_BUFFER_LIMIT之後,Spark調用JDK的API時,會根據NIO_BUFFER_LIMIT對ByteBuffer的limit進行調整,這樣子IOUtils看到的ByteBuffer大小只有NIO_BUFFER_LIMIT。這樣子每次只拷貝了NIO_BUFFER_LIMIT(256KB),調用4次總共拷貝了1MB的數據。從這個例子可以看到NIO_BUFFER_LIMIT會減少內存的拷貝。

當然,如果NIO_BUFFER_LIMIT的值沒選好,太大了就變回原來的情況,太小則會產生太多的寫操作,都會影響性能。

最後,遇到類似的問題,你可以嘗試使用git blame來找到對應的pull request,只要不是太早的代碼,一般會有pull request,上面會有比較詳細的討論。比如NIO_BUFFER_LIMIT在GitHub上的鏈接是:https://github.com/apache/spark/blame/v2.1.0/common/network-common/src/main/java/org/apache/spark/network/protocol/MessageWithHeader.java#L48

然後,通過commit,你會找到pull request是:[SPARK-14290][CORE][Network] avoid significant memory copy in nettyamp;amp;#x27;s transferTo by liyezhang556520 · Pull Request #12083 · apache/spark


推薦閱讀:

如何使用 parquet file 建立一個 RDD 的同時讀進 case class 結構?
決策樹演算法簡介及Spark MLlib調用
spark源碼分析--任務執行

TAG:Spark |