標籤:王家林談spark效能最佳化第十季之全球獨家揭秘spark統一記憶體管理!
內容:
1、傳統的Spark記憶體管理的問題;
2、Spark統一記憶體管理;
3、 展望;
==========傳統的Spark記憶體管理的問題============
Spark記憶體分為三部分:
Execution:Shuffles、Joins、Sort、Aggregations等等,預設情況下佔用,spark.shuffle.memoryfraction預設是0.2;
Storage:Persist(Canche)、Large Task Result、Torrent類型的Broadcast等,預設佔用,spark.storage.memoryfraction預設是0.6;
Other:Program Object、Metadata、code,預設0.2
有記憶體使用量安全系統(safetyfraction):0.8,也就是Execution和Storage等只能使用配置記憶體的80%,就是上面只能是0.16、0.48、0.16
如果單台機器不強,則在Execution中的資料會一直spill到磁碟中,則shuffle的效能就會很慢,單台機器越強,結果就越強,所以建叢集的時候,追求單台機器(記憶體)的極致,而非單純的拼機器的數量。
如果沒有多少large task result,則可以適當提高Execution。
同理,如果storage如果不做cache,則是非常大的記憶體浪費。
傳統的記憶體配置的模型,對spark人才的需求很高。
很好的證明:
650) this.width=650;" src="/e/u261/themes/default/images/spacer.gif" style="background:url("/e/u261/lang/zh-cn/images/localimage.png") no-repeat center;border:1px solid #ddd;" alt="spacer.gif" />
650) this.width=650;" src="/e/u261/themes/default/images/spacer.gif" style="background:url("/e/u261/lang/zh-cn/images/localimage.png") no-repeat center;border:1px solid #ddd;" alt="spacer.gif" />
從Execution角度說說怎麼樣去分配記憶體的,分配記憶體有個ShuffleMemoryManager、TaskMemoryManager、ExecutorMemoryManager。
一個具體的Task過來,可能會佔滿Executor的記憶體,
==========Spark統一記憶體管理============
UnifiedMemoryManager,Spark1.6保證至少有300M的空間可以用
/**
* A [[MemoryManager]] that enforces a soft boundary between execution and storage such that
* either side can borrow memory from the other.
*
* The region shared between execution and storage is a fraction of (the total heap space - 300MB)
* configurable through `spark.memory.fraction` (default 0.75). The position of the boundary
* within this space is further determined by `spark.memory.storageFraction` (default 0.5).
* This means the size of the storage region is 0.75 * 0.5 = 0.375 of the heap space by default.
*
* Storage can borrow as much execution memory as is free until execution reclaims its space.
* When this happens, cached blocks will be evicted from memory until sufficient borrowed
* memory is released to satisfy the execution memory request.
*
* Similarly, execution can borrow as much storage memory as is free. However, execution
* memory is *never* evicted by storage due to the complexities involved in implementing this.
* The implication is that attempts to cache blocks may fail if execution has already eaten
* up most of the storage space, in which case the new blocks will be evicted immediately
* according to their respective storage levels.
*
* @param storageRegionSize Size of the storage region, in bytes.
* This region is not statically reserved; execution can borrow from
* it if necessary. Cached blocks can be evicted only if actual
* storage memory usage exceeds this region.
*/
object UnifiedMemoryManager {
// Set aside a fixed amount of memory for non-storage, non-execution purposes.
// This serves a function similar to `spark.memory.fraction`, but guarantees that we reserve
// sufficient memory for the system even for small heaps. E.g. if we have a 1GB JVM, then
// the memory used for execution and storage will be (1024 - 300) * 0.75 = 543MB by default.
private val RESERVED_SYSTEM_MEMORY_BYTES = 300 * 1024 * 1024
統一記憶體管理,當executor記憶體不夠的時候,會向storage借,有多少借多少
當strorage記憶體不夠,也不會讓executor釋放出來
王家林老師名片:
中國Spark第一人
新浪微博:http://weibo.com/ilovepains
公眾號:DT_Spark
部落格:http://blog.sina.com.cn/ilovepains
手機:18610086859
QQ:1740415547
郵箱:[email protected]
本文出自 “一枝花傲寒” 部落格,謝絕轉載!
王家林談Spark效能最佳化第十季之全球獨家揭秘Spark統一記憶體管理!