對hadoop task進行profiling的幾種方法整理

在hadoop中,當一個job的調試完成,執行成功後,job的開發者接下來該思考的問題通常就是:如何將job跑的更快,更加高效,更節省資源呢?這個話題其實是一個老生常談的話題了,很多有經驗的工程師,開發人員和機構都分享過類似的經驗。通常來說,應用程序千變萬化,程序邏輯也不盡相同,程序的執行瓶頸通常也不盡相同,有的job是IO密集型的作業,那麼優化其算法效率意義就不大,而有的job是CPU密集型的,那麼對其中間結果壓縮,或者調整類似io.sort.mb,io.sort.factor等參數也就沒有什麼太大作用,優化程序算法肯定會有更大收益。

    所以在大多數情況下,寫job,調試job,測試,上線運行,這套開發mapreduce應用程序的流程通常很多開發團隊都走的很順。但這並不是最難的,事情到這裏也還遠遠不算完,程序哪裏不高效,哪裏消耗過多資源,哪裏是瓶頸,如何優化,這一系列的問題,根據在下的經驗,是開發團隊考慮的相對不多的地方。

    通常應用程序的開發者發現自己的hadoop job跑的不夠高效,不夠快的時候,第一時間想到的,是給hadoop平臺的開發團隊寫郵件,說你hadoop平臺又怎麼怎麼樣,害的我的job跑的不夠高效,然後在郵件的最後還附加上一句:“請hadoop平臺開發團隊多多考慮用戶的建議和用戶體驗,優化hadoop,滿足我這個什麼什麼job的需求,不然我就 @#¥%#¥%#”。而其實大部分情況下,只要稍微關注一下自己的程序,稍微進行一些優化,作業的執行效率就會高很多。說到這裏內心又開始有些激動,還是言歸正傳吧……

     剛纔說到作業效率和瓶頸的問題,怎麼發現作業的瓶頸呢?用戶怎麼知道他的作業的在哪個階段最耗時,哪個地方最耗內存呢?其實hadoop提供了用戶tunning自己job的方法,其中profiling tasks就是其中一種。

     和debug task一樣,profiling一個運行在分佈式hadoop環境下的mapredeuce job是比較困難的。但在hadoop中,是可以讓用戶針對某些tasks進行profiling採集的,當這些task執行完後,將這些profiling日誌保存的文件發送到作業的提交client機器上,然後用戶就可以用自己熟悉的工具來分析這些profiling日誌,進行tasks執行瓶頸的分析。

 

使用方法:

  在JobConf中,有幾個配置選項是可以用來控制task profiling行爲的。比如對一個job,想要開啓對其tasks的profiling功能,並設置profiling相應的HPROF參數,可以按如下方式:

 

conf.setProfileEnabled(true);
conf.setProfileParams("-agentlib:hprof=cpu=samples,heap=sites,depth=6," +
"force=n,thread=y,verbose=n,file=%s");
conf.setProfileTaskRange(true, "0-2");

第一行表示打開profiling task的功能,該功能默認情況下是關閉的。調用該接口相當於設置配置選項 mapred.task.profile=true,可以利用這種方式在hadoop job提交命令行上動態指定。

 

第二行是通過conf接口來設置對tasks進行HPROF 的profiling的採集參數,採用profiling enable的方式運行的tasks,會採用每個task一個獨立的JVM的運行方式運行(即使enable了job的jvm reuse功能)。HPROF相關的採集參數設置,可以見其他資料。該選項也可以通過設置 mapred.task.profile.params 選項來指定。

 

第三行表示對job的哪些tasks需要進行profiling採集,第一true參數表示採集的是map tasks的性能數據,false的話表示採集reduce的性能數據,第二個參數表示只採集編號爲0,1,2的tasks的數據,(默認爲0-2)。如果想要採集除2,3,5編號的tasks,可以設置該參數爲: 0-1,4,6-

 

Example

   還是拿wordcount來舉例,提交job命令如下:

 

bin/hadoop jar hadoop-examples-0.20.2-luoli.jar wordcount /
  -D mapred.reduce.tasks=10 /
  -D keep.failed.task.files=fales /
  -D mapred.task.profile=true /
  -D mapred.task.profile.params="-agentlib:hprof=cpu=samples,heap=sites,depth=6,force=n,thread=y,verbose=n,file=%s" /
  $input /
  $output

 

這樣,當job運行時,就會對前三個task進行profiling的採集,採集信息包括cpu的採樣信息,內存分配的信息數據,stack trace 6層的堆棧信息。這裏需要注意的是,由於前三個tasks被進行了HPROF的性能採樣,所以這幾個tasks的執行效率會受到一定的影響,profiling的信息越詳細,性能影響就越大。如下圖,前三個map就明顯比其他的map運行的要慢很多。

不過這種運行方式通常都不是線上運行方式,而是用來進行優化調試,所以關係不大。

 

而當job運行完成後,這三個tasks對應的profiling日誌也會會傳到提交機器上,供用戶分析判斷。如下圖:

 

與此同時,tasks在tasktracker上也將這些profiling日誌信息記錄到了一個profile.out的日誌文件中,該文件通常位於tasktracker機器上的上${HADOOP_HOME}/logs/userlogs/${attempt_id}下,和該task的stderr,stdout,syslog保存在同一個目錄下,如下圖:

 

該文件中的內容,還可以通過taskdetails.jsp的頁面查看到。如下圖:

 

 

有了這些信息,相信對於任何一位hadoop應用程序的開發者來說,就擁有了足夠的定位job瓶頸的信息了。MR的應用程序開發同學,請優化您的job吧~~


發佈了37 篇原創文章 · 獲贊 1 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章