Spark源码[6]-Task内存

2020-05-24  本文已影响0人  蠟筆小噺没有烦恼

位于spark-core模块的org.apache.spark.memory.TaskMemoryManager

1 简介

TaskMemoryManager用于管理单个任务尝试的内存分配与释放,其依赖于MemoryManger的内存管理能力。
比较重要的成员包括:

PAGE_NUMBER_BITS = 13 #存储页号,寻址page的位数,使用长整型64位的最高13位
OFFSET_BITS = 64 - PAGE_NUMBER_BITS #保存编码后的偏移量的位数,用长整型的底51位
MAXIMUM_PAGE_SIZE_BYTES = ((1L << 31) - 1) * 8L #最大page大小
MASK_LONG_LOWER_51_BITS = 0x7FFFFFFFFFFFFL #长整型的底51位掩码
PAGE_TABLE_SIZE = 1 << PAGE_NUMBER_BITS #Page表的page数量,8192页
pageTable = new MemoryBlock[PAGE_TABLE_SIZE] #page表,实际为Page的数组,page也就是MemoryBlock

2 提供的方法

TaskMemoryManager有两个重要的内存申请方法:acquireExecutionMemory是针对堆内内存,按照字节进行计数。而allocatePage是和Tungsten一起引入,使用页存来管理内存,并且支持堆外内存的申请。

2.1 申请执行内存-acquireExecutionMemory

位于spark-core模块的org.apache.spark.memory.TaskMemoryManager

1 简介

TaskMemoryManager用于管理单个任务尝试的内存分配与释放,其依赖于MemoryManger的内存管理能力。
比较重要的成员包括:

PAGE_NUMBER_BITS = 13 #存储页号,寻址page的位数,使用长整型64位的最高13位
OFFSET_BITS = 64 - PAGE_NUMBER_BITS #保存编码后的偏移量的位数,用长整型的底51位
MAXIMUM_PAGE_SIZE_BYTES = ((1L << 31) - 1) * 8L #最大page大小
MASK_LONG_LOWER_51_BITS = 0x7FFFFFFFFFFFFL #长整型的底51位掩码
PAGE_TABLE_SIZE = 1 << PAGE_NUMBER_BITS #Page表的page数量,8192页
pageTable = new MemoryBlock[PAGE_TABLE_SIZE] #page表,实际为Page的数组,page也就是MemoryBlock

2 提供的方法

TaskMemoryManager有两个重要的内存申请方法:acquireExecutionMemory是针对堆内内存,按照字节进行计数。而allocatePage是和Tungsten一起引入,使用页存来管理内存,并且支持堆外内存的申请。

2.1 申请执行内存-acquireExecutionMemory

申请内存方法

用于位内存消费者指定大小(字节),如果内存不足,调用MemoryConsumer的spill先进行内存释放。

  1. 首先调用MemoryManager.acquireExecutionMemory申请目标大小的执行内存;
  2. 如果申请到的内存小于期望的内存大小(got < required);则遍历所有MemoryConsumer(除了当前申请者),尝试进行spill数据溢写。遍历中如果有consumer释放了内存,则调用MemoryManager.acquireExecutionMemory将内存加到got中,如果释放的内存和已申请到的内存大于了需要申请的内存,则停止下面的consumer遍历。
  3. 如果遍历了所有的MemoryConsumer,got依然小于required,则,对当前的MemoryConsumer进行spill,并调用MemoryManager.acquireExecutionMemory做最后尝试。
  4. 将当前consumer加入到consumers中,并返回实际申请到的内存。

2.2 以页的方式申请内存-allocatePage

用于位内存消费者指定大小(字节),如果内存不足,调用MemoryConsumer的spill先进行内存释放。

  1. 首先调用MemoryManager.acquireExecutionMemory申请目标大小的执行内存;
  2. 如果申请到的内存小于期望的内存大小(got < required);则遍历所有MemoryConsumer(除了当前申请者),尝试进行spill数据溢写。遍历中如果有consumer释放了内存,则调用MemoryManager.acquireExecutionMemory将内存加到got中,如果释放的内存和已申请到的内存大于了需要申请的内存,则停止下面的consumer遍历。
  3. 如果遍历了所有的MemoryConsumer,got依然小于required,则,对当前的MemoryConsumer进行spill,并调用MemoryManager.acquireExecutionMemory做最后尝试。
  4. 将当前consumer加入到consumers中,并返回实际申请到的内存。
上一篇下一篇

猜你喜欢

热点阅读