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

相关文章
相关标签/搜索