map的环形内存缓冲区 stm32串口环形缓冲区

map的环形内存缓冲区

博客分类: hadoop源码解读

HadoopMapreduceApache工作

hadoop在执行MapReduce任务时,在map阶段,map函数产生的输出,并不是直接写入磁盘的。为了提高效率,它将输出结果先写入到内存中(即环形内存缓冲区,默认大小100M),再从缓冲区(溢)写入磁盘。

下面我们就来看看这段代码。

1、找到环形内存缓冲区

在运行job时,有条输出:

09/04/07 12:34:35 INFO mapred.MapTask: io.sort.mb = 100

上面的io.sort.mb,即map环形内存缓冲区的大小。

在org.apache.hadoop.mapred.MapTask中的第764行找到“io.sort.mb”

第781行:

Java代码  

kvbuffer=newbyte[maxMemUsage-recordCapacity];

kvbuffer是在第715行定义的:

Java代码  

privatebyte[]kvbuffer;//mainoutputbuffer

看,这个内存缓冲区竟然是个byte数组!!

2、什么时候溢写到磁盘的?

Java代码  

第762行:

finalfloatspillper=job.getFloat("io.sort.spill.percent",(float)0.8);

//溢写比:默认是0.8,就是说,缓存区80%满了的时候,就要将数据从内存溢写到磁盘了

这100M,还分成2块:数据缓存和记录缓存

第707行:

privatefinalint[]kvoffsets;//indicesintokvindices

//这个int型的数组就是记录缓存

第941行:

//sortbykey

returncomparator.compare(kvbuffer,

kvindices[ii+KEYSTART],

kvindices[ii+VALSTART]-kvindices[ii+KEYSTART],

kvbuffer,

kvindices[ij+KEYSTART],

kvindices[ij+VALSTART]-kvindices[ij+KEYSTART]);

//在内存缓冲区中按key进行排序

综上,溢写发生在:

1) 溢写比设置了<1的值,并且该值到了的时候

2) 溢写比为1,缓存满了的时候

3、缓冲区怎么成环形的?

答:通过折行。

----------------------------------

“折行写”

Java代码  

第1038行:

booleanbuffull=false;//缓存是否满了

//这里的“满”,有2种情况:

1)bufindex+len>bufvoid

//就是说,达到了末尾

//但是这种情况,可能不是真的满了

//因为,在数组0-bufstart之间,可能还有很大的空置空间

2)bufindex+len>bufstart

//由于缓冲区已经成“环”,这种情况,是真的满了。

第1039行:

booleanwrap=false;//是否需要“折行写”

//“折行写”的条件:

1)bufstart<=bufend&&bufend<=bufindex

//buffer是一段连续的区域,还没有形成“环”

2)(bufvoid-bufindex)+bufstart>len

//数组末尾,加上数组开头的空间能够存储当前数据

//真正执行“折行写”的代码(Line1101-1107):

if(buffull){//这里满足上面第1种buffull=true的条件,否则

//将先溢写至磁盘后,再到达这里。

finalintgaplen=bufvoid-bufindex;

System.arraycopy(b,off,kvbuffer,bufindex,gaplen);

len-=gaplen;

off+=gaplen;

bufindex=0;

}

----------------------------------

“折行写”后的reset

Java代码  

Line996-1014的reset()方法:

这个方法被调用的地点:第895行,

第893行,在collect方法中:

if(bufindex<keystart){

//wrappedthekey;resetrequired

bb.reset();

keystart=0;

}

//如果key被“折写”成2段,则reset缓冲区

//这时候:一个key有一半写在了数组末尾,另一半写在了数组列头时候

这个方法被调用的时候(bufindex<keystart==true):

一定是,序列化后的key被写入缓存区,而且是被wrap(折行)写入的!

这个方法里的解释:

protectedsynchronizedvoidreset()throwsIOException{

//spillLockunnecessary;Ifspillwraps,then

//bufindex<bufstart<bufendsocontentionisimpossible

//astalevalueforbufstartdoesnotaffectcorrectness,since

//wecanonlygetfalsenegativesthatforcethemore

//conservativepath

intheadbytelen=bufvoid-bufmark;

//headbytelen的意思是:被“折行”写入的key的前段部分

//bufvoid是缓冲区的右边界

//bufmark是缓冲区中上次存值后的右边界

//bufvoid-bufmark:就是被“折行”写入的key的前半段

bufvoid=bufmark;

if(bufindex+headbytelen<bufstart){

//基本上这个条件成立的可能性比较大,

//它的意思是说:整个key的长度(前半段的长度是headbytelen,存在缓冲区最后面;后半段的长度是bufindex,存在缓冲区的最前面)在bufstart之间的空间能存得下

//那么接下来的2行代码:把这个key的两端,都移到缓冲区的最前面!

System.arraycopy(kvbuffer,0,kvbuffer,headbytelen,bufindex);

System.arraycopy(kvbuffer,bufvoid,kvbuffer,0,headbytelen);

bufindex+=headbytelen;

}else{

//这种情况真的很难达到:要求溢写比(io.sort.spill.percent)为1,并且bufstart很靠近0的时候

//这种情况是:buffer真的很满了(bufstart-bufindex<headbytelen),以至于在bufstart之前的空间不足以存储一个key

byte[]keytmp=newbyte[bufindex];

System.arraycopy(kvbuffer,0,keytmp,0,bufindex);

bufindex=0;

//把这个key分2次写入out

//也就是说:

//1)这个key,先从kvbuffer缓存中删除

//2)接下来,应该是将缓存中数据溢写到磁盘上

//3)out中的这个key再次写入清空后的缓存里!

//估计在清空缓存前,这个都会被阻塞。

out.write(kvbuffer,bufmark,headbytelen);

out.write(keytmp);

}

}

}

4、“成环”示意图

上面的代码一定看的眼花缭乱吧?呵呵,我一开始看的时候,也被弄得很糊涂。请看下面的示意图,就会对这个环形缓冲有个好的理解了。



5、“溢写”过程

map的环形内存缓冲区 stm32串口环形缓冲区
Java代码  

bufend=bufmark;//在startSpill方法中

sortAndSpill();

bufstart=bufend;

即:

溢写完毕后,原来的bufmark变成了bufstart

6、缓存为什么要设计成环形的?有什么好处?

答:使输入输出并行工作,即“写缓冲”可以和“溢写”并行。“溢写”工作由单独的线程来做。

Java代码  

解读“溢写”代码:

bufend=bufmark;//在startSpill方法中

sortAndSpill();

bufstart=bufend;

1)溢写前:

bufend=bufmark;

则溢写的范围是:从bufstart到bufend。

2)在溢写的过程中,bufmark还是有可能增长的!

3)溢写完毕,bufstart=bufend;

*** THE END***

  

爱华网本文地址 » http://www.aihuau.com/a/25101012/131218.html

更多阅读

串口线与并口线的区别 串口并口区别

串口线与并口线的区别——简介我们经常碰到串口线或者并口线,究竟他们有什么区别呢?串口线与并口线的区别——工具/原料串口线,并口线串口线与并口线的区别——方法/步骤串口线与并口线的区

串口通信的分类 基于fpga的串口通信

串口通信的分类串口通信可以分为同步通信和异步通信两类。同步通信是按照软件识别同步字符来实现数据的发送和接收,异步通信是一种利用字符的再同步技术的通信方式。2.1同步通信同步通信是一种连续串行传送数据的通信方式,一次通信

串口并口硬盘连接详细步骤 硬盘串口和并口的区别

提前声明:我并不是计算机硬件或维修专业,同时也根本没有学习过类似的课程。都是自己瞎琢么出来的,如有不足,敬请多提意见。一般的情况是两个串口的硬盘连接,或是两个并口的硬盘连接,所以,自认为这篇文章叙述的是最复杂的状态,即串口硬盘和

cc2531USBdongle实现MT模式数据转发串口 stm32f103双串口转发

由于项目需求要实现CC2531USBdongle的MT模式来实现dongle的数据转发功能,框架简图1所示。PC端实现了MT模式,也可以用Ztool。总结起来就是dongle在MT模式下接收串口数据(数据满足MT格式),然后将数据解析为具体方法,接收到node端发送的数据

如何用VB编写串口程序 如何编写串口驱动程序

VB控件MSComm功能介绍VB中的MSComm 控件通过串行端口传输和接收数据,为应用程序提供串行通讯功能。MSComm控件在串口编程时非常方便,程序员不必去花时间去了解较为复杂的API函数,而且在VC、VB、Delphi等语言中均可使用。 Microsoft Com

声明:《map的环形内存缓冲区 stm32串口环形缓冲区》为网友唯有自己强大分享!如侵犯到您的合法权益请联系我们删除