Spark Tungsten揭祕 Day3 內存分配和管理內幕

Spark Tungsten揭祕 Day3

內存分配和管理內幕

恭喜Spark2.0發佈,今天會看一下2.0的源碼。java

今天會講下Tungsten內存分配和管理的內幕。Tungsten想要工做,要有數據源和數據結構,這時候會涉及到內存管理,而內存管理也是後續作不少分析和邏輯控制的基礎。數組

內存分配

咱們從內存分配的入口MemoryAllocator開始:數據結構

allocate() 分配的是一塊連續乾淨的內存空間,若是不是乾淨的話,會先用zero方法,把裏面填充爲0。咱們注意到操做的數據結構都是MemoryBlock。
Snip20160804_30jvm

MemoryBlock中pageNumber字段是public級別的,方便爲TaskMemoryManager修改。內部有一個obj,onheap方式的話是一個字節數組,若是是offheap方式分配的是本地對象的指針。
其中會使用到一個Platform類,至關於Java Bean級別,提供對於數據一系列獲取方法。
Snip20160804_31大數據

至於具體的內存分配是如何操做的,咱們看一下具體的實現,首先是HeapMemoryAllocator,註釋裏說明能夠分配16G原生數組。編碼

從allocate裏面看到,對於大數據量狀況,會有一個Pool來管理,Pool中會預先存放各類尺寸的memory塊,在獲取時直接獲取;小數據量的化通過字節對齊以後以後返回對象。
Snip20160804_35spa

UnsafeMemoryAllocator中直接使用Platform的方法分配,這個方法沒有實現,是經過jni,用C和C++實現的,其實就是用C語言分配個空間,跟new一個數組沒有多大區別。
Snip20160804_32指針

在申請內存時,若是不夠的話會spill(溢出到磁盤),以後看下release的內容,繼續進行獲取。
Snip20160804_38orm

內存管理

不管是UNSAFE仍是HEAP的方式,都是採用了MemoryBlock來分配,這有一個很大的好處,是讓咱們的內存使用者Task,能統一被內存的管理者TaskMemoryManager來分配.對象

TaskMemoryManager是如何來管理被task分配的內存呢,統一的方法是將地址編碼成64字節的長整數。可是對於off-heap和on-heap編碼方式是不一樣。

  • off-heap方式下,編碼比較簡單,直接將物理地址轉成64位long便可。
  • 而在on-heap方式下,有一個很嚴重的問題,就是gc時候會致使內存發生改變。因此須要採用間接的方式來保存。實際管理時,咱們會創建一個page table,其中會索引到實際的地址,而在編碼長整數時,前13個字節表明page編號,指向page table中的某個page,然後51位則記錄數據在page中的offset。
  • 不少page構成了page table,咱們能夠定位8192張page,大小是被java數組的上限來限制。理論上一個jvm能支持35TB。

咱們看下TaskMemoryManager中的代碼,pageTable是個MemoryBlock的數組,會使用一個BitSet來進行索引。
Snip20160804_37

最後,咱們有個問題,onheap模式下操做的時候,會根據offset來操做,有沒有說操做多大的空間?
由於地址是64位的長整數,onheap方式得到邏輯地址時,會把起始offset和長度都編碼進去,獲取64位長整數時,有一套讀取方式,雖然開始只知道offset,默認會知道下面有幾位空間,也就是數據有多長。
Snip20160804_39

欲知後事如何,且聽下回分解!

DT大數據天天晚上20:00YY頻道現場授課頻道68917580

相關文章
相關標籤/搜索