map 端 spill 详解

20
Map Map spill spill 端端 端端 端端 2011-09-19

Upload: montague-santos

Post on 03-Jan-2016

128 views

Category:

Documents


7 download

DESCRIPTION

Map 端 spill 详解. 俞灵 2011-09-19. 一个简单的例子. Wordcount 的 map 函数 public void map(LongWritable key, Text value, OutputCollector output, Reporter reporter) throws IOException { String line = value.toString(); - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Map 端 spill 详解

MapMap 端端 spillspill 详解详解

俞灵2011-09-19

Page 2: Map 端 spill 详解

一个简单的例子一个简单的例子Wordcount 的 map 函数

◦ public void map(LongWritable key, Text value, ◦ OutputCollector<Text, IntWritable> output, ◦ Reporter reporter) throws IOException {◦ String line = value.toString();◦ StringTokenizer itr = new StringTokenizer(line);◦ while (itr.hasMoreTokens()) {◦ word.set(itr.nextToken());◦ output.collect(word, one);◦ }◦ }

output.collect(word, one); 是如何实现的呢

Page 3: Map 端 spill 详解

Mapreduce-64Mapreduce-64 前前 collectcollect 原原理理原理

◦使用三个数组 kvoffsets 记录索引 Kvindices key value 索引 Kvbuffer 存储 record

◦ Kvoffsets 或 Kvbuffer 达到 limit 便开始 spill

◦按照 partition 对 record 排序并 spill

Page 4: Map 端 spill 详解

参数解释参数解释初始值

◦ sm = Io.sort.mb << 20◦ rp = io.sort.record.percent ◦ sp = io.sort.spill.percent

三个数组长度◦ kvoffsets = new int[ sm*rp /16]◦ Kvindices = new int[ 3*sm*rp /16]◦ Kvbuffer = new byte[sm - sm*rp ]

两个 limit◦ softBufferLimit = kvbuffer.length * sp◦ softRecordLimit = kvoffsets.length * sp

Page 5: Map 端 spill 详解

初始状态

….

….

kvoffsets

kvindices

kvbuffer

kvstart

kvendkvinde

x

bufstart

bufendbufind

exbufmar

k

Page 6: Map 端 spill 详解

加入一条记录◦ (key,val) 长度分别为 (3,4)

….

….

kvoffsets

kvindices

kvbuffer

kvstart

kvendkvinde

x

bufstart

bufend

bufindex=7

bufmark=7

partition03

Page 7: Map 端 spill 详解

参数设置参数设置设置参数

◦sp=0.8◦rp=0.05◦sm=32000◦recordNum=sm*rp/16=1000◦kvlimit=recordNum*sp=800◦bufLen=sm*(1-rp)=30400◦buflimit=bufLen*sp=24320

Page 8: Map 端 spill 详解

Spill 开始前

….

kvoffsets

kvindices

kvbuffer

kvstart

kvendkvinde

x

bufstart

bufend

bufindex=9022

bufmark=9022

partition03

partition

57

…..

03

800

bvlimit=800

buflimit=24320

buflvoid= 30400

Page 9: Map 端 spill 详解

Spill 结束后

kvoffsets

kvindices

kvbuffer

kvstart

kvendkvinde

x

bufstart

bufend

bufindex=9925

bufmark=9924

partition03

partition

57

…..

03

800

bvlimit=800

buflimit=24320

buflvoid= 30400

900

9924

Page 10: Map 端 spill 详解

Collect 流程collect(key,

value)

spilllock

计算kvfull,kvsoftlimit

开始 spill

是否达到 limit且在 spill

是否 full

等待 spill 结束

是否 full

unlock

写 key

Key 是否被分割

移动 key, 重置kvoid

写 value

写索引 , 更新kvindex

yes

yes

yes no

yes

nono

no

Page 11: Map 端 spill 详解

write 流程 Write

Spilling?

是否有记录

yes

达到 limit或写不下

写得下

no

复制数据更新bufindex

计算buffull,warp

计算 buflimit

Start spill

MapBufferTooSmall

写得下

Wait spill

写得下

yes

yes

yes

yes

yes

no

no

no

no

no

Page 12: Map 端 spill 详解

流程解释流程解释三个触发 spill 的地方

◦ kv 达到 limit(kvstart == kvend && kvsoftlimit)◦ buf 达到 limit

kvstart == kvend, kvend != kvindex 有 record bufsoftlimit || (buffull && !wrap))

◦ 单条记录过长 kvend == kvindex 无 record buffull && !wrap

Wrap◦ True: 可以存下单条记录 , 需要调头◦ 处理一条记录垮首尾的情况

Page 13: Map 端 spill 详解

流程解释流程解释Block 的地方

◦ Kvfull◦ buffull && !wrap ( 无法写入下一条记录 )

单条记录超过剩余容量◦ MapBufferTooSmallException◦ spillSingleRecord

Bufvoid 的作用◦ 可用 buf 大小◦ 防止 key 调头 ( 利于 spill 时计算 )

问题◦ 内存未充分利用◦ Block 地方两个 , 程序慢

Page 14: Map 端 spill 详解

Mapreduce-64Mapreduce-64原理

◦把三个数组合并成一个数组◦总内存超过限制才 spill

问题◦单个数组如何存储 int 和 byte

Creates a view of byte buffer as an int buffer

kvmeta = ByteBuffer.wrap(kvbuffer).asIntBuffer();

◦如何存储索引和 record 双向存储

Page 15: Map 端 spill 详解

Mapreduce-64 原理图

Page 16: Map 端 spill 详解

Mapreduce-64 原理图

Page 17: Map 端 spill 详解

Collect 流程collect(key,

value)

计算bufremain

lock

Bufremain 是否小于

0

是否可回收内存 l

计算 used, buflimit

是否在spill

是否要spill

回收内存

开始 spill, 重置参数

写 key

Key 是否被分割

移动 key, 重置kvoid

写 value

写索引 , 更新kvindex

no

unlock

no

no

no

no

yes

yes

yes

yes

yes

Page 18: Map 端 spill 详解

Write 流程Write()

复制数据更新bufindex

BufferTooSmall

计算bufremainBufremain 是否小

于 0

lock

计算可用空间

计算blockwrite

是否在spill

是否blockwri

te

是否可回收内存 l

回收内存

是否有记录

Startspill 重置bufmark

是否blockwrit

e

等待 spill

是否blockwrit

e

noyes

yes

no

no

no

no

nono

yes

yes

yes

yes

yes

Page 19: Map 端 spill 详解

流程解释流程解释Spill 条件

◦ bufsoftlimit && kvindex != kvend( 有记录 )◦ 下一条记录过长

Block 的情况 : blockwrite◦ distkvi <= distkve? distkvi <= len + 2 * METASIZE: distkve

<= len || distanceTo(bufend, kvbidx) < 2 * METASIZE;

Bufremain 的计算◦ min( distanceTo(bufindex, 4*kvindex) - 2 * METASIZE,softLimit -

bUsed) - METASIZE;

◦ min( distanceTo(bufend, newPos), min(distanceTo(newPos, 4*kvend), softLimit) ) - 2 * METASIZE

预留两个 metasize ?

Page 20: Map 端 spill 详解

sortAndSpillsortAndSpill 流程流程修改前后流程不变

◦ 获取文件名及输出流◦ 获取需要 spill 的 kv 首尾位置◦ 根据 partition 对 kv 排序◦ 根据是否需要 combine 进行输出

由 partitnion 从小到大输出 相同 partition 合并成一条记录输出

◦ Spill 计数器加一 , 关闭输出流