dr.elephant啓發式算法詳解

Metrics測量指標

1. Used Resources

Job使用資源的數量,單位是:GB Hours

計算方式

我們將任務的資源使用定義爲:所有mapper任務和所有reducer任務的資源使用的總和。

例如:

有如下的job:

4 mappers with runtime {12, 15, 20, 30} mins.

4 reducers with runtime {10 , 12, 15, 18} mins.

向yarn申請的容器大小爲:4 GB

那麼,

所有mapper使用的資源: 4 * (( 12 + 15 + 20 + 30 ) / 60 ) GB Hours = 5.133 GB Hours

所有reducer使用的資源: 4 * (( 10 + 12 + 15 + 18 ) / 60 ) GB Hours = 3.666 GB Hours

Job使用的總資源= 5.133 + 3.6666 = 8.799 GB Hours

2.Wasted Resources

資源浪費就是指資源浪費的數量,我們通過GB

hours或者百分比方式展示job浪費資源的數量。

計算方式

爲了計算資源的浪費情況,我們需要先計算下面的指標:

1)Map和reduce任務中浪費的最小的內存大小

2)Map和reduce任務的運行時間

 

任務浪費的最小的內存大小= 申請的yarn容器的大小- 所有的任務中最大使用的內存大小

任務浪費的資源= 任務浪費的最小內存大小* 任務運行的時間,

job總的資源浪費 = 所有的任務浪費的資源總和

 

對於每一個任務我們定義如下:

peak_memory_used := task使用的內存上界

runtime := task運行時長

 

通過所有task中的最大使用的物理內存(max_physical_memory)和虛擬內存(virtual_memory)可以計算出任意task的peak_memory_used,又由於每個任務的上界通過max_physical_memory來確定,因此我們可以說每個任務的peak_memory_used可以通過下面的公式計算出來:

peak_memory_used = Max(max_physical_memory, virtual_memory/2.1)

其中2.1是集羣的內存因子(該參數yarn.nodemanager.vmem-pmem-ratio對應的值)

 

每個task的最小內存浪費可以通過下面的公式計算:

wasted_memory = container_size - peak_memory_used

 

每個任務的最小資源浪費可以通過下面的公式計算:

wasted_resource = wasted_memory * runtime

 

總的資源的浪費情況就等於所有任務的wasted_resource的總和

3.Runtime

運行時間指標展示作業總的運行時間。

計算方式

Job的運行時間是通過job的完成時間減去job提交到yarn的資源管理器的時間計算出來的。

例如:

Job的開始時間是:1461837302868 ms

Job的完成時間是:1461840952182 ms

Job的運行時間是:1461840952182 - 1461837302868= 3649314 ms or 1.01 hours

4.Wait time

Job的等待時間是指job運行中花費在等待狀態總的時間。

計算方式

對於每一個job我們定義如下的名詞:

ideal_start_time := 所有任務都應該完成啓動的理想的時間

finish_time := 任務完成時間

task_runtime := 任務運行時間

 

- Map tasks

對於map任務,我們定義如下:

ideal_start_time := job的開始時間

 

我們找出所有map任務中最長運行時間(task_runtime_max)和最後的完成時間( finish_time_last ),那麼job中mapper的總的等待時間就可以通過如下的公式計算出來:

mapper_wait_time = finish_time_last - (ideal_start_time + task_runtime_max)

 

- Reduce tasks

對於reducer任務,我們定義如下:

 

ideal_start_time := 通過獲取的reducer慢開始的百分比(mapreduce.job.reduce.slowstart.completedmaps:這個參數的含義是,當Map Task完成的比例達到該值後纔會爲Reduce Task申請資源,默認是0.05)並找到map任務完成之後最先開始的那個reducer,就可以計算出該參數

 

我們找到reducer任務最大運行時間( task_runtime_max)和最後完成的時間( finish_time_last )

那麼job的reducer任務的總等待時間就可以使用如下公式計算出來:

reducer_wait_time =finish_time_last - (ideal_start_time + task_runtime_max)

 

total_wait_time = mapper_wait_time + reducer_wait_time

例如:

 

如上圖:

對於map任務:

ideal_start_time = t1

task_runtime_max = Map_1對應的運行時間

finish_time_last = t4

mapper_wait_time = t4 – Map_1對應的運行時間– t1

對於reduce任務:

ideal_start_time = t2

task_runtime_max = Reduce_3對應的運行時間

finish_time_last = t6

reducer_wait_time = t6 -

Reduce_3對應的運行時間- t2

總的等待時間:

total_wait_time =mapper_wait_time + reducer_wait_time

 

MapReduce算法分析

1.Mapper數據傾斜

數據進入到Mapper作業中後,有可能會發生數據的傾斜,這種數據傾斜主要是考慮到HDFS文件大小差別太大導致的。

1)判斷依據

根據每個map task運行的時間和數據量兩個指標進行判定。

2)原理

Mapper數據傾斜啓發式算法(mapper

data skew heuristic)會將所有的Mapper分成兩部分,其中一部分的所有作業(task)的平均數據量會大於另一部分的平均數據量,之後根據這兩個組的平均數據量的差值的絕對值/這兩組數據中平均數據量的最小值來判斷數據傾斜程度。時間方面的傾斜程度算法一樣。

此圖中的A和B兩組的平均數據量和平均運行時間都差不多,沒有發生數據傾斜

此圖中A和B兩組的平均運行時間差不多,但是平均數據量差別很大,最終導致嚴重程度爲Critical,這說明該作業讀取的hdfs中的數據文件大小差別太大,1)可能是有很多小文件, 2)也可能是文件大小超過block大小的10%以上一點,導致超出的部分又佔用了一個block

3)計算步驟

(1)遞歸的計算作業輸入數據量的平均值,然後根據作業的輸入量平均值將所有的作業分成兩組Group_A 和Group_B。

(2)計算各組的平均值,並求出數據量小的組的平均值(minAvg)和兩組平均值之差的絕對值(diffAvgAbs)

(3)求出誤差( diffAvgAbs/ minAvg ),根據誤差和給定的誤差級別(比如:{2, 4, 8, 16})計算嚴重程度severity

(4)計算出數據量小的那組的的task數量,並根據配置的task數量級別(比如:{10, 50, 100, 200})計算出task數量的嚴重程度taskSeverity

(5)取數據量大的那組的平均數據量,並根據配置的文件大小級別(比如:{1d / 8, 1d / 4, 1d / 2, 1d}其中的每個值需要乘以block的大小)計算出task數據量的嚴重程度fileSeverity

(6)求出上面計算出來的嚴重程度的最小值作爲map 數據傾斜程度的結果。

 

2.Mapper GC

Mapper GC會分析任務的GC效率。它會計算出所有mapper的平均GC時間佔平均CPU時間的比例。避免打擾用戶,該算法在代碼中設置了很寬鬆的範圍(觀察線上跑的結果發現確實沒有GC報警的情況),但是如果分析的結果仍然報警的話,說明你的代碼確實需要優化了。

1)判斷依據

平均GC時間佔平均CPU時間的比例,比例越高,嚴重程度越大,通常來說代碼需要優化。

2)原理

計算出所有作業的平均的CPU使用時間、平均運行時間以及平均GC的時間。我們要計算Mapper GC嚴重度的最小值,這個值可以通過平均運行時間和平均垃圾回收時間佔平均CPU總消耗時間的比例來計算。

3)計算步驟

(1)計算出平均CPU使用時間(avgCPU)、平均運行時間(avgRuntime)、平均GC時間(avgGC)。

(2)計算出平均GC時間佔平均CPU時間的比例(gcRatio)

(3)使用gcRatio和誤差級別(比如:{0.01d, 0.02d, 0.03d, 0.04d})計算嚴重程度gcSeverity

(4)使用平均運行時間和運行時間的級別(比如:{5, 10, 12, 15} 單位:分鐘數)計算運行時間的嚴重程度runtimeSeverity

(5)取上面兩個嚴重程度的最小值作爲gc的嚴重程度。

3.Mapper的內存消耗

分析每個Mapper實際內存的消耗,並檢查作業消耗的內存比例以及向yarn申請的容器的總內存,該指標用於分析用戶申請的容器內存是否合理,比如:你申請了10G的yarn容器的內存,但是實際消耗內存卻只有1G,說明你的任務浪費了很多內存資源,此時就會顯示嚴重級別爲critical,說明你需要減少每個mapper向yarn容器申請的內存資源的大小。

1)判斷依據

task任務平均使用內存佔向yarn容器所申請的內存的比例。比例越低說明內存資源浪費程度越高,需要優化,反之則說明資源利用率越高越好。

2)原理

計算平均內存消耗佔用向yarn資源容器申請的內存大小比率,使用該比率結合設置的內存利用率級別判斷mapper對內存的消耗是否合理。

此圖對內存的消耗就不合理,因爲申請的內存高達24G,但是實際使用的內存最大卻只有6G左右,平均內存使用才3.7G左右,嚴重浪費內存資源。

3)計算步驟

(1)計算所有task的平均物理內存消耗(avgPhysicalMemory)、平均虛擬內存消耗(avgVirtualMemory)、平均運行時間(avgRuntime),並從該應用的配置文件中獲取向yarn容器申請的內存大小(containerMemory)

(2)計算平均物理內存消耗(avgPhysicalMemory)和向yarn容器申請的內存大小(containerMemory)的比值(ratio)。

(3)使用上面的比值(ratio)結合內存利用率級別(比如:{0.6d, 0.5d, 0.4d, 0.3d}),計算出嚴重程度severity。

(4)再使用向yarn容器申請的內存大小(containerMemory)與容器級別(比如:{1.1d,

1.5d, 2.0d, 2.5d} 中的每一個值需要乘以yarn的配置文件中配置的默認的容器大小)計算出申請的容器的嚴重程度containerSeverity

(5)計算出上面兩個嚴重級別的最小值作爲內存消耗的嚴重級別

4.Mapper的運行速度

分析Mapper代碼的運行效率。通過這些分析可以知道mapper屬於CPU消耗型的,或者是mapper處理的數據量過大。通過這個能夠分析出mapper運行速度快慢和處理的數據量大小之間的關係。

1)判斷依據

         所有task的運行速度的中值作爲判斷mapper運行速度的依據,而運行速度是通過每個task的輸入數據/運行時長得到的。

2)原理

         通過計算每個task的運行速度的中值,結合配置的磁盤的讀取速度,判斷出mapper任務的執行速度,但是需要排除運行時間過短導致的錯誤的結果。

此任務運行速度就太慢了,也可以推斷出該任務是CPU消耗型任務。

3)計算步驟

(1)計算出運行速度的中值(medianSpeed)、運行時間的中值(medianRuntime)、輸入數據量的中值(medianDataSize)

(2)使用運行速度中值(medianSpeed)結合運行速度的級別(比如:{1d / 2, 1d / 4, 1d / 8, 1d / 32} 每個值需要乘以磁盤的讀取速度,默認100M/s)計算出嚴重級別speedSeverity。

(3)再使用運行時間的中值(medianRuntime)結合運行時間級別(比如:{5, 10, 15, 30})計算出運行時間的嚴重程度runtimeSeverity

(4)取speedSeverity和runtimeSeverity兩個嚴重級別的較小者作爲運行速度的嚴重級別。

5.Mapper溢出

該算法從磁盤IO的角度去評測mapper的性能。mapper溢出比例(溢出的記錄數/總輸出的記錄數)是衡量mapper性能的一個重要指標:如果這個值接近2,表示幾乎每個記錄都溢出了,並臨時寫到磁盤兩次(其中一次發生在內存排序緩存溢出時,另一次發生在歸併排序所有溢出的切換時)。當這些發生時表明mapper輸入輸出的數據量過大了。

1)判斷依據

總的溢出記錄數和總的輸出記錄數的比值。

2)原理

計算出所有task的溢出記錄數和所有task的輸出記錄數的比值,使用該比值進行mapper溢出嚴重程度的判斷,該比值越大說明輸入輸出的數據量過大,需要進行優化以提高運行速度。

3)計算步驟

(1)計算出所有task的總的溢出記錄數(totalSpillRecords)、總的輸出記錄數(totalOutputRecords),並計算出其比值(ratioSpill)

(2)使用上面計算的比值結合配置的溢出級別(比如:{2.01d, 2.2d, 2.5d, 3.0d})計算出溢出的嚴重程度spillSeverity。

(3)根據task的數量計算出任務數的嚴重程度taskNumberSeverity

(4)取上面兩個小的嚴重程度作爲溢出嚴重程度。

6.Mapper運行時間

這部分分析mappers的數量是否合適。通過分析結果,我們可以更好的優化任務中mapper的數量這個參數的設置。有以下兩種情況發生時,這個參數的優化就顯得很迫切了:

1)Mapper的運行時間很短,可能的原因如下:

mapper的數量過多

mapper的平均運行時間很短

文件尺寸太小

2)Mapper的運行時間很長,可能的原因包括:

mapper的數量很少

mapper的平均運行時間很長

文件的大小過大(個別文件是GB級別)

1)判斷依據

         根據所有task運行的平均時長進行嚴重程度的判斷

2)原理

         首先計算出所有task的平均運行時間,之後根據該平均運行時間計算出最短和最長的任務運行時長嚴重級別,取兩個嚴重級別中較大的作爲運行時長的嚴重級別。

3)計算步驟

(1)計算出所有task的平均輸入大小(avgInputSize)、平均運行時長(avgRuntime)(2)根據平均運行時長(avgRuntime)結合短運行時長級別(比如:{10, 4, 2, 1} 其中的每個值代表的是分鐘數)計算出短運行時長的嚴重級別shortSeverity

(3)根據任務數結合任務數的級別(比如:{50, 101, 500, 1000})計算出任務數的嚴重程度taskNumberSeverity

(4)取上面shortSeverity和taskNumberSeverity的較小值作爲短運行時長的嚴重級別realShortSeverity

(5)根據平均運行時長(avgRuntime)結合長運行時長級別(比如:{15, 30, 60, 120} 其中的每個值代表的是分鐘數)計算出長運行時長的嚴重級別longSeverity

(6)取realShortSeverity和longSeverity總的較大則作爲運行時長的嚴重級別

7.Reducer數據傾斜

分析進入到每個Reduce中的數據是否有傾斜。該分析能夠發現Reducer中是否存在這種情況,將Reduce分爲兩部分,其中一部分的輸入數據量明顯大於另一部分的輸入數據量。

1)判斷依據

根據每個reduce task運行的時間和數據量兩個指標進行判定。

2)原理

Mapper數據傾斜啓發式算法(reducer

data skew heuristic)會將所有的Reducer分成兩部分,其中一部分的所有作業(task)的平均數據量會大於另一部分的平均數據量,之後根據這兩個組的平均數據量的差值/這兩組數據中平均數據量的最小值來判斷數據傾斜程度。時間方面的傾斜程度算法一樣。

3)計算步驟

(1)遞歸的計算作業輸入數據量的平均值,然後根據作業的輸入量平均值將所有的作業分成兩組Group_A 和Group_B。

(2)計算各組的平均值,並求出數據量小的組的平均值(minAvg)和兩組平均值之差的絕對值(diffAvgAbs)

(3)求出誤差( diffAvgAbs/ minAvg ),根據誤差和給定的誤差級別(比如:{2, 4, 8, 16})計算嚴重程度severity

(4)計算出數據量小的那組的的task數量,並根據配置的task數量級別(比如:{10, 50, 100, 200})計算出task數量的嚴重程度taskSeverity

(5)取數據量大的那組的平均數據量,並根據配置的文件大小級別(比如:{1d / 8, 1d / 4, 1d / 2, 1d}其中的每個值需要乘以block的大小)計算出task數據量的嚴重程度fileSeverity

(6)求出上面計算出來的嚴重程度的最小值作爲map 數據傾斜程度的結果。

8.Reducer GC

Reduce GC用於分析任務的GC效率,能夠計算並告訴我們GC時間佔所用CPU時間的比例。該算法在代碼中設置了很寬鬆的範圍,避免打擾用戶,但是如果分析的結果任然報警的話,說明你的代碼確實需要優化了。

1)判斷依據

平均GC時間佔平均CPU時間的比例,比例越高,嚴重程度越大,通常來說代碼需要優化。

2)原理

首先,會計算出所有任務的平均CPU消耗時間、平均運行時間以及平均垃圾回收所消耗的時間。然後,算法會根據平均運行時間以及垃圾回收時間佔平均CPU時間的比值來計算出最低的嚴重度。

3)計算步驟

(1)計算出平均CPU使用時間(avgCPU)、平均運行時間(avgRuntime)、平均GC時間(avgGC)。

(2)計算出平均GC時間佔平均CPU時間的比例(gcRatio)

(3)使用gcRatio和誤差級別(比如:{0.01d, 0.02d, 0.03d, 0.04d})計算嚴重程度gcSeverity

(4)使用平均運行時間和運行時間的級別(比如:{5, 10, 12, 15} 單位:分鐘數)計算運行時間的嚴重程度runtimeSeverity

(5)取上面兩個嚴重程度的最小值作爲gc的嚴重程度。

9.Reducer內存消耗

分析每個Reducer實際內存的消耗,並檢查作業消耗的內存比例以及向yarn申請的容器的總內存,該指標用於分析用戶申請的容器內存是否合理,比如:你申請了10G的yarn容器的內存,但是實際消耗內存卻只有1G,說明你的任務浪費了很多內存資源,此時就會顯示嚴重級別爲critical,說明你需要減少每個Reducer向yarn容器申請的內存資源的大小。

1)判斷依據

task任務平均使用內存佔向yarn容器所申請的內存的比例。比例越低說明內存資源浪費程度越高,需要優化,反之則說明資源利用率越高越好。

2)原理

計算平均內存消耗佔用向yarn資源容器申請的內存大小比率,使用該比率結合設置的內存利用率級別判斷reducer對內存的消耗是否合理。

此圖對內存的消耗就不合理,因爲申請的內存高達24G,但是實際使用的內存最大卻只有6G左右,平均內存使用才3.7G左右,嚴重浪費內存資源。

3)計算步驟

(1)計算所有task的平均物理內存消耗(avgPhysicalMemory)、平均虛擬內存消耗(avgVirtualMemory)、平均運行時間(avgRuntime),並從該應用的配置文件中獲取向yarn容器申請的內存大小(containerMemory)。

(2)計算平均物理內存消耗(avgPhysicalMemory)和向yarn容器申請的內存大小(containerMemory)的比值(ratio)。

(3)使用上面的比值(ratio)結合內存利用率級別(比如:{0.6d, 0.5d, 0.4d, 0.3d}),計算出嚴重程度severity。

(4)再使用向yarn容器申請的內存大小(containerMemory)與容器級別(比如:{1.1d,

1.5d, 2.0d, 2.5d} 中的每一個值需要乘以yarn的配置文件中配置的默認的容器大小)計算出申請的容器的嚴重程度containerSeverity 。

(5)計算出上面兩個嚴重級別的最小值作爲內存消耗的嚴重級別。

10.Reducer時間

這部分分析Reducer的執行效率,可以幫助我們更好的配置任務中reducer的數量;當出現以下兩種情況時,說明Reducer的數量需要進行調優:

1)Reducer過多,hadoop任務可能的表現是:

Reducer數量過多

Reducer的運行時間很短

2)Reducer過少,hadoop任務可能的表現是:

Reducer數量過少

Reducer運行時間很長

1)判斷依據

         根據所有task運行的平均時長進行嚴重程度的判斷

2)原理

         首先計算出所有task的平均運行時間,之後根據該平均運行時間計算出最短和最長的任務運行時長嚴重級別,取兩個嚴重級別中較大的作爲運行時長的嚴重級別。

任務數多,運行時長過短,屬於嚴重級別的

運行時長計算:屬於嚴重級別的

任務數方面計算:屬於None級別的

取上面兩個級別的較小者None級別作爲最終的嚴重級別。

3)計算步驟

(1)計算出所有task的最大運行時長(minRuntime)、最小運行時長(maxRuntime)、平均運行時長(avgRuntime)(2)根據平均運行時長(avgRuntime)結合短運行時長級別(比如:{10, 4, 2, 1} 單位:分鐘)計算出短運行時長的嚴重級別shortSeverity

(3)根據任務數結合任務數的級別(比如:{50, 101, 500, 1000})計算出任務數的嚴重程度taskNumberSeverity

(4)取上面shortSeverity和taskNumberSeverity的較小值作爲短運行時長的嚴重級別realShortSeverity

(5)根據平均運行時長(avgRuntime)結合長運行時長級別(比如:{15, 30, 60, 120}單位:分鐘數)計算出長運行時長的嚴重級別longSeverity

(6)取realShortSeverity和longSeverity總的較大則作爲運行時長的嚴重級別

11.洗牌和排序

分析reducer消耗的總時間以及reducer在進行洗牌和排序時消耗的時間,通過這些分析,可以判斷reducer的執行效率。

1)判斷依據

         所有task的平均shuffle時長和平均sort時長進行判斷的,取兩者中較大的作爲洗牌和排序的嚴重級別

2)原理

         首先計算出所有的task的平均shuffle時長和平均sort時長,之後再分別與平均執行時長(totalTime - shuffleTime - sortTime)進行相除,計算出shuffle和sort的嚴重級別,取兩者中較大的作爲洗牌和排序的嚴重級別。

其中後面的X代表倍數的意思,計算方式是:avgShuffleTime / avgCodeTime 和avgSortTime /

avgCodeTime。

此圖顯示shuffle的時間很長,但是sort的時間很短,說明你需要調整slowstart參數"mapreduce.job.reduce.slowstart.completedmaps"從0.90 調大一些,要小於1.0。但是需要注意的是,調整此參數可以降低shuffle的時間,但是可能會增加整個job的運行時間。 

3)計算步驟

(1)計算出所有task的平均執行時長(avgExecuteTime)、平均shuffle時長(avgShuffleTime)、平均sort時長(avgSortTime)

(2)將平均shuffle時長結合運行時長的級別(比如:{1, 5, 10, 30} 單位:分鐘數)計算出shuffle的嚴重級別shuffleSeverity

(3)計算shuffleRatio = avgShuffleTime* 2 / avgExecuteTime,之後使用shuffleRatio結合運行比率級別(比如:{1, 2, 4, 8})計算出shuffle運行比率級別shuffleRatioSeverity

(4)取shuffleSeverity 和shuffleRatioSeverity的較小者作爲真正的shuffle嚴重級別realShuffleSeverity

(5)將平均sort時長(avgSortTime)結合運行時長的級別(比如:{1, 5, 10, 30}單位:分鐘數)計算出sort的嚴重級別sortSeverity

(6)計算sortRatio = avgSortTime * 2 /avgExecuteTime,之後使用sortRatio結合運行比率級別(比如:{1, 2, 4, 8})計算出sort運行比率級別sortRatioSeverity

(7)取sortSeverity和sortRatioSeverity的最小值作爲真正的shuffle嚴重級別realSortSeverity

(8)取realShuffleSeverity和realSortSeverity中較大者作爲洗牌和排序的嚴重級別

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章