spark從1.6.0開始內(nèi)存管理發(fā)生了變化眼姐,原來的內(nèi)存管理由StaticMemoryManager實(shí)現(xiàn)昌阿,現(xiàn)在被稱為Legacy
,在1.5.x和1.6.0中運(yùn)行相同代碼的行為是不同的锻霎,為了兼容Legacy
,可以通過spark.memory.useLegacyMode
來設(shè)置,默認(rèn)該參數(shù)是關(guān)閉的。
前面有一篇介紹spark內(nèi)存管理的文章spark內(nèi)存概述,現(xiàn)在介紹1.6.0的內(nèi)存管理,由UnifiedMemoryManager實(shí)現(xiàn)瓤狐。
1.6.0的統(tǒng)一內(nèi)存管理如下:
主要有三部分組成:
1 Reserved Memory
這部分內(nèi)存是預(yù)留給系統(tǒng)使用,是固定不變的批幌。在1.6.0默認(rèn)為300MB(RESERVED_SYSTEM_MEMORY_BYTES = 300 * 1024 * 1024
)础锐,這一部分內(nèi)存不計(jì)算在spark execution和storage中,除了重新編譯spark和spark.testing.reservedMemory
,Reserved Memory是不可以改變的荧缘,spark.testing.reservedMemory
不推薦使用在實(shí)際運(yùn)行環(huán)境中皆警。是用來存儲(chǔ)Spark internal objects,并且限制JVM的大小截粗,如果executor的大小小于1.5 * Reserved Memory = 450MB 信姓,那么就會(huì)報(bào) “please use larger heap size”的錯(cuò)誤,源碼如下鸵隧。
val minSystemMemory = reservedMemory * 1.5
if (systemMemory < minSystemMemory) {
throw new IllegalArgumentException(s"System memory $systemMemory must " +
s"be at least $minSystemMemory. Please use a larger heap size.")
}
2 User Memory
分配Spark Memory剩余的內(nèi)存,用戶可以根據(jù)需要使用意推《固保可以存儲(chǔ)RDD transformations
需要的數(shù)據(jù)結(jié)構(gòu),例如菊值, 重寫spark aggregation
,使用mapPartition transformation
外驱,通過hash table
來實(shí)現(xiàn)aggregation
,這樣使用的就是User Memory
腻窒。在1.6.0中昵宇,計(jì)算方法為(“Java Heap” – “Reserved Memory”) * (1.0 – spark.memory.fraction)
,默認(rèn)為(“Java Heap” – 300MB) * 0.25
儿子,比如4GB的heap大小瓦哎,那么User Memory
的大小為949MB。由用戶來決定存儲(chǔ)的數(shù)據(jù)量典徊,因此要遵守這個(gè)邊界杭煎,不然會(huì)導(dǎo)致OOM。
3 Spark Memory
計(jì)算方式是(“Java Heap” – “Reserved Memory”) * spark.memory.fraction
卒落,在1.6.0中羡铲,默認(rèn)為(“Java Heap” – 300MB) * 0.75
。例如推的大小為4GB儡毕,那么Spark Memory
為2847MB也切。Spark Memory
又分為Storage Memory
和Execution Memory
兩部分。兩個(gè)邊界由spark.memory.storageFraction
設(shè)定腰湾,默認(rèn)為0.5雷恃。但是兩部分可以動(dòng)態(tài)變化,相互之間可以借用费坊,如果一方使用完倒槐,可以向另一方借用。先看看兩部分是如何使用的附井。
Storage Memory 用來存儲(chǔ)
spark cached data
也可作為臨時(shí)空間存儲(chǔ)序列化unroll
讨越,broadcast variables
作為cached block
存儲(chǔ),但是需要注意永毅,這是unroll源碼把跨,unrolled block
如果內(nèi)存不夠,會(huì)存儲(chǔ)在driver
端沼死。broadcast variables
大部分存儲(chǔ)級(jí)別為MEMORY_AND_DISK
着逐。Execution Memory 存儲(chǔ)Spark task執(zhí)行過程中需要的對象,例如,Shuffle中map端中間數(shù)據(jù)的存儲(chǔ)耸别,以及hash aggregation中的hash table健芭。如果內(nèi)存不足,該空間也容許spill到磁盤秀姐。
Execution Memory
不可以淘汰block吟榴,不然執(zhí)行的時(shí)候就會(huì)fail,如果找不到block囊扳。Storage Memory
中的內(nèi)容可以淘汰。Execution Memory
滿足兩種情況可以向Storage Memory
借用空間:
Storage Memory
還有free空間Storage Memory
大于初始化時(shí)的空間("Spark Memory" * spark.memory.storageFraction = (“Java Heap” – “Reserved Memory”) * spark.memory.fraction * spark.memory.storageFraction
)
Storage Memory
只有在Execution Memory
有free空間時(shí)兜看,才可以借用锥咸。