Spark性能優(yōu)化第十季之Spark統(tǒng)一內(nèi)存管理1、傳統(tǒng)的Spark內(nèi)存管理的問題 2、Spark統(tǒng)一內(nèi)存管理 3、展望 Spark內(nèi)存分為三部分:Execution、Sotrage、Other; Shuffle,當(dāng)內(nèi)存不夠的時(shí)候下,磁盤IO很大負(fù)擔(dān) 10個(gè)Task并行,則會(huì)把內(nèi)存分為10份,實(shí)際運(yùn)行時(shí)Task可能會(huì)沾滿整個(gè)空間,其他任務(wù)分配不到空間。 即使一個(gè)Task不會(huì)把內(nèi)存用完,另外一個(gè)Task申請(qǐng)內(nèi)存,它有一個(gè)算法,如果申請(qǐng)的內(nèi)存不夠,Task不會(huì)自動(dòng)Spill到disk,默認(rèn)放一部分?jǐn)?shù)據(jù)到內(nèi)存中,有個(gè)百分比,這樣不斷重復(fù),既消耗CPU又消耗內(nèi)存。 這時(shí)就要Spill到磁盤 1、分布式系統(tǒng)的性能殺手是Shuffle,join、aggregation可能需要用很大內(nèi)存,但是給他分配的很少,這不是有效的內(nèi)存使用方法 2、假設(shè)需要Spill,計(jì)算時(shí)還要從磁盤讀到內(nèi)存,這時(shí)磁盤IO是不能承受的 3、Storage空間不夠,計(jì)算結(jié)果丟失可能需要重新計(jì)算 4、假設(shè)Task占滿內(nèi)存,其他Cores都在空閑狀態(tài) 5、即使Spill數(shù)據(jù)到磁盤,它還是要申請(qǐng)一部分百分比的空間放一部分?jǐn)?shù)據(jù)的 Execution分配內(nèi)存: ShuffleMemoryManager、TaskMemoryManager、ExecutorMemoryManager 最安全、廉價(jià)的STORAGE_LEVEL是MEMORY_AND_DISK_SER Iterator一條一條讀取數(shù)據(jù)叫Unroll,無法一次性把所有的數(shù)據(jù)放進(jìn)去,因?yàn)榭赡躉OM。Unroll的內(nèi)存空間是從Storage空間中獲得的,Unroll過程中會(huì)放盡量多的數(shù)據(jù)放入Storage中,Spark給了它一個(gè)參數(shù),spark.storage.unroll.fraction默認(rèn)也是0.2;unroll失敗的話則直接放到硬盤。 UnifiedMemoryManagement: Execution Memory可以直接訪問Storage Memory,Storage Memory可以訪問Execution Memory,這兩個(gè)可以互相借內(nèi)存。 默認(rèn)兩部分加在一起為總堆大小-300MB,300MB可配置:spark.testing.reserveMemory RESERVED_SYSTEM_MOMORY_BYTES = 3 * 1024 * 1024是保留的內(nèi)存大小。 spark.memory.storageFraction 默認(rèn)為0.5,所以其最大空間為0.75 * 0.5 = 0.375倍的,且可以找execution memory借。如果借的還不夠的話,則有不同的處理方式 Storage可以向execution借內(nèi)存,當(dāng)execution需要內(nèi)存時(shí),則會(huì)將Storage的內(nèi)存drop掉,知道足夠的空間夠自己使用。 相反execution也可以向Storage借內(nèi)存,當(dāng)Storage的Memory不夠的時(shí)候不會(huì)將Execution的內(nèi)存drop掉,這是因?yàn)橛?jì)算的時(shí)候牽扯很多東西,drop后太過于復(fù)雜。

|