漫談Spark內存管理(三) : 存儲內存在哪些地方用到?

漫談Spark內存管理(一)有提到問題:“ Spark中用到內存的地方有哪些?存儲內存主要消耗在哪些地方?執行內存主要消耗在哪些地方?”。本文就從存儲內存使用的角度聊聊spark中哪些地方需要用到存儲內存。

MemoryManger.acqurieStorageMemory的調用

我們知道,spark中使用內存之前必須先通過MemoryManager申請內存,那麼從MemoryManager的acquire系列方法就可以找出哪些地方有申請內存。MemoryManager有三個acquire方法,分別是acquireStorageMemory, acquireUnrollMemory, acquireExecutionMemory. 其中,acquireUnrollMemory就是直接調用了acquireStorageMemory方法(針對UnifiedMemoryManager而言)。

本文主要討論acquireStorageMemory的調用路徑。除了UnifiedMemoryManager.acquireUnrollMemory外,acquireStorageMemory方法在MemoryStore中有兩處調用,一個是在MemoryStore.putBytes中:

另一處在MemoryStore.putIterator中:

我們以MemoryStore.putIterator的調用路徑爲例(MemoryStore.putBytes的調用路徑和MemoryStore.putIterator大體相似,感興趣的童鞋可以自行查閱源碼),分析存儲內存申請主要來自哪些模塊。

RDD block相關的存儲內存申請

1) ShuffleMapTask/ResultTask.runTask -> RDD.iterator -> RDD.getOrCompute -> BlockManager.getOrElseUpdate -> BlockManager.doPutIterator -> MemoryStore.putIteratorAsBytes -> MemoryStore.putIterator

2) ShuffleMapTask/ResultTask.runTask -> RDD.iterator -> RDD.getOrCompute -> BlockManager.getOrElseUpdate -> BlockManager.doPutIterator -> MemoryStore.putIteratorAsValues -> MemoryStore.putIterator

3) ShuffleMapTask/ResultTask.runTask -> RDD.iterator -> RDD.getOrCompute -> BlockManager.getOrElseUpdate -> BlockManager.getLocalValues -> BlockManager.maybeCacheDiskValuesInMemory -> MemoryStore.putIteratorAsValues -> MemoryStore.putIterator

4) ShuffleMapTask/ResultTask.runTask -> RDD.iterator -> RDD.getOrCompute -> BlockManager.getOrElseUpdate -> BlockManager.get -> BlockManager.getLocalValues -> BlockManager.maybeCacheDiskValuesInMemory -> MemoryStore.putIteratorAsValues -> MemoryStore.putIterator

5) ShuffleMapTask/ResultTask.runTask -> RDD.iterator -> RDD.getOrCompute -> RDD.computeOrReadCheckpoint -> WriteAheadLogBackedBlockRDD.compute -> WriteAheadLogBackedBlockRDD.compute$getBlockFromWriteAheadLog -> blockManager.putBytes -> BlockManager.doPutBytes -> MemoryStore.putIteratorAsValues -> MemoryStore.putIterator

分析:當RDD的storage level包括memory時(也就是調用了RDD.cache或RDD.persist將RDD數據緩存到了memory中),Task在計算得到RDD分區數據時會申請存儲內存將數據緩存在內存中。

Broadcast block相關的存儲內存申請

1) TorrentBroadcast.writeBlocks -> BlockManager.putSingle -> BlockManager.putIterator -> BlockManager.doPutIterator -> MemoryStore.putIteratorAsValues -> MemoryStore.putIterator

2) TorrentBroadcast.readBroadcastBlock -> BlockManager.putSingle -> BlockManager.putIterator -> BlockManager.doPutIterator -> MemoryStore.putIteratorAsValues -> MemoryStore.putIterator

3) TorrentBroadcast.readBroadcastBlock -> BlockManager.getLocalValues -> BlockManager.maybeCacheDiskValuesInMemory -> MemoryStore.putIteratorAsValues -> MemoryStore.putIterator

分析:對廣播變量進行存儲/緩存也會用到存儲內存。

RDD block Replication相關的存儲內存申請

1) NettyBlockRpcServer.receive -> BlockDataManager.putBlockData -> BlockManager.putBytes -> BlockManager.doPutBytes -> MemoryStore.putIteratorAsValues -> MemoryStore.putIterator

2) NettyBlockRpcServer.receiveStream -> BlockDataManager.putBlockDataAsStream -> BlockManager.putBytes -> BlockManager.doPutBytes -> MemoryStore.putIteratorAsValues -> MemoryStore.putIterator

分析:當RDD的storage level中的_replication大於1時,BlockManager需要將block數據發到另一個遠程結點以備份,此時BlockManager會向遠程結點發送UploadBlock消息,遠程結點在收到該消息後會申請存儲內存以存放收到的block數據。

Task運行結果數據相關的存儲內存申請

TaskRunner.run -> BlockManager.putBytes -> BlockManager.doPutBytes -> MemoryStore.putIteratorAsValues -> MemoryStore.putIterator

分析:TaskRunner處理task結果數據時,如果task結果數據大於maxDirectResultSize,則會將其存儲到本地blockManager,然後將block的meta數據返回給driver,並且這個時候用的storeage level是MEMORY_AND_DISK_SER, 所以會向MemoryManager申請存儲內存。

Streaming receiver相關的存儲內存申請

1) ReceiverSupervisorImpl.pushAndReportBlock -> BlockManagerBasedBlockHandler.storeBlock -> BlockManager.putIterator -> BlockManager.doPutIterator -> MemoryStore.putIteratorAsBytes -> MemoryStore.putIterator

2) ReceiverSupervisorImpl.pushAndReportBlock -> BlockManagerBasedBlockHandler.storeBlock -> BlockManager.putBytes -> BlockManager.doPutBytes -> MemoryStore.putIteratorAsValues -> MemoryStore.putIterator

分析:Spark streaming中的receiver-based模式下,ReceiverSupervisorImpl類也會申請存儲內存以存放block數據,這部分後面寫到spark streaming相關文章,再詳細討論。

說明

1. 本文源碼分析基於spark 2.4.0版本

2. 如有錯誤,望讀者指出

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