hadoop在執行mapreduce任務時,在map階段,map函式產生的輸出,並不是直接寫入磁碟的。為了提高效率,它將輸出結果先寫入到記憶體中(即環形記憶體緩衝區,預設大小100m),再從緩衝區(溢)寫入磁碟。
下面我們就來看看這段**。
[size=medium][b]1、找到環形記憶體緩衝區[/b][/size]
在執行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行:
kvbuffer = new byte[maxmemusage - recordcapacity];
kvbuffer是在第715行定義的:
private byte kvbuffer; // main output buffer
[b]看,這個記憶體緩衝區竟然是個byte陣列!![/b]
[size=medium][b]2、什麼時候溢寫到磁碟的?[/b][/size]
第762行:
final float spillper = job.getfloat("io.sort.spill.percent",(float)0.8);
// 溢寫比:預設是0.8,就是說,快取區80%滿了的時候,就要將資料從記憶體溢寫到磁碟了
這100m,還分成2塊:資料快取和記錄快取
第707行:
private final int kvoffsets; // indices into kvindices
// 這個int型的陣列就是記錄快取
第941行:
// sort by key
return comparator.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,快取滿了的時候
[size=medium][b]3、緩衝區怎麼成環形的?[/b][/size]
答:通過折行。
----------------------------------
「折行寫」
第1038行:
boolean buffull = false; // 快取是否滿了
// 這裡的「滿」,有2種情況:
1) bufindex + len > bufvoid
// 就是說,達到了末尾
// 但是這種情況,可能不是真的滿了
// 因為,在陣列0-bufstart之間,可能還有很大的空置空間
2) bufindex + len > bufstart
// 由於緩衝區已經成「環」,這種情況,是真的滿了。
第1039行:
boolean wrap = false; // 是否需要「折行寫」
// 「折行寫」的條件:
1) bufstart <= bufend && bufend <= bufindex
// buffer是一段連續的區域,還沒有形成「環」
2) (bufvoid - bufindex) + bufstart > len
// 陣列末尾,加上陣列開頭的空間能夠儲存當前資料
// 真正執行「折行寫」的**(line1101-1107):
if (buffull)
----------------------------------
「折行寫」後的reset
[size=medium][b]4、「成環」示意圖[/b][/size]
上面的**一定看的眼花繚亂吧?呵呵,我一開始看的時候,也被弄得很糊塗。請看下面的示意圖,就會對這個環形緩衝有個好的理解了。
[img]
[size=medium][b]5、「溢寫」過程[/b][/size]
bufend = bufmark; // 在startspill方法中
sortandspill();
bufstart = bufend;
即:溢寫完畢後,原來的bufmark變成了bufstart
[size=medium][b]6、快取為什麼要設計成環形的?有什麼好處?[/b][/size]
答:使輸入輸出並行工作,即「寫緩衝」可以和「溢寫」並行。「溢寫」工作由單獨的執行緒來做。
解讀「溢寫」**:
bufend = bufmark; // 在startspill方法中
sortandspill();
bufstart = bufend;
1)溢寫前:
bufend = bufmark;
則溢寫的範圍是:從bufstart到bufend。
2)在溢寫的過程中,bufmark還是有可能增長的!
3)溢寫完畢,bufstart = bufend;
*** the end***
環形緩衝區
include include include include include define buffsize 1024 1024 define min x,y x y x y pthread mutex t lock pthread mutex initializer struct cycle b...
環形緩衝區
define print buf size 16 1024 static char g pcnetprintbuf 環形緩衝區的首位址 static int g ireadpos 0 環形緩衝區讀的位置 static int g iwritepos 0 環形緩衝區寫的位置 intinit 判斷環形緩...
環形緩衝區
環形緩衝區要維護兩個索引,分別對應寫入端 w 和讀取端 r 寫入 push 的時候,先確保環沒滿,然後把資料複製到 w 所對應的元素,最後 w 指向下乙個元素 讀取 pop 的時候,先確保環沒空,然後返回 r 對應的元素,最後 r 指向下乙個元素。上述的操作並不複雜,不過有乙個小小的麻煩 空環和滿環...