SlideShare a Scribd company logo
Hadoopソースコード読み会
Shuffleを読んでみる
山下 真一
2
背景
● 某案件より:「Reduce処理に時間が掛かりすぎる!」
→ リソースネックではなかった
→ 処理ログを見るとShuffleで延々と時間が掛かる!
→ これが有名なShuffleのワナね!
いきなり大きな壁にぶつかった2年前の秋・・・
月日は流れ・・・
● 2010年8月 0.21.0リリース!
→ ある人曰く:「Shuffleは少々手を入れたぜ!」
→ おぉ!これは確認せずにはいられなゐ!
といういことで、Shuffleがどうなったか読んでみた。
3
前提
● Hadoop 0.21.0
● 対象は、Shuffle時にMap処理結果を取得する部分
● 大まかな流れのみで詳細や異常系までは読んでいません!
● JobTrackerはlocalモードではないです!
● 読み違いは、ご容赦を!
4
Shuffleへの道のり
● Hadoopの実装では、Map処理やReduce処理はTaskTrackerそのものでは
なく、TaskTrackerより生成されるChildが実行
● Child : org.apache.hadoop.mapred.Child
Childは、Map処理やReduce処理を実行する (L:217)
● taskFinal.run()よりReduceTask.run()が実行
● Hadoopでは、ReduceTask内でShuffleが処理されるの
で、ReduceTask.run()を追いかける
5
ReduceTask
● ReduceTask : org.apache.hadoop.mapred.ReduceTask
● ReduceTask内でShuffleインスタンス生成 (L:353)
● Shuffle : org.apache.hadoop.mapreduce.task.reduce
– 0.21.0より導入されたクラス
– Shuffleコンストラクタ内でShuffleScheduler, MergeManagerイン
スタンスを生成 (L:88, L:92)
● Shuffleインスタンスのrun()を実行 (L:362)
Combine処理は、
Spillする場合に処理される
6
ShuffleScheduler
● mapLocations : Map<String, MapHost> / HashMap
● pendingHosts : Set<MapHost> / HashSet
● finishedMaps : final boolean[]
● totalMaps : final int
● remainingMaps : int
● copySucceed() : Map処理結果の取得が成功したときに実行
● addKnownMapOutput() : Map処理結果情報(ホスト名, MapID)を追加
● getHost() : Map処理ホスト情報取得
● getMapForHost() : Map処理ホストで実行したMap処理情報取得
● waitUntilDone() : Map処理結果取得の完了までwait
7
MergeManager
● IntermediateMemoryToMemoryMergerスレッド
● mapreduce.reduce.merge.memtomem.enabled = trueの場合
● InMemoryMergerスレッド
● 特定の閾値を超えた場合、MemoryMerge → Spill 実行
● OnDiskMergerスレッド
● DiskでのMerge
● reserve() : Map処理結果取得のためのメモリ確保
● ディスク or メモリ or null (メモリ上で扱えるがメモリを大量に使用し
ている場合)
● canShufflleToMemory() : Memory or Disk
● finalMerge() : Map処理結果を全て取得した後の最後に実行
8
Shuffle
● Shuffle.run()では、2種類のスレッドを生成と起動
● EventFetcher (L:106) : Map処理の状況を確認する
● Fetcher (L:112) : Map処理結果を取得する,複数のスレッドを生成
– mapreduce.reduce.shuffle.parallel.copiesプロパティで指定
● デフォルト5
● 全てのMap処理が完了するまで無限ループ待ち (L:119)
● PROGRESS_FREQUENCY : 2000ミリ秒でハードコーディング
9
EventFetcher – その1
● EventFetcher.run() : 無限ループでMap処理実行状況を把握
● getMapCompletionEvents()を呼び出し (L:66)
● ループ内でThread.sleep(SLEEP_TIME)を実行 (L:72)
– SLEEP_TIME : 1000ミリ秒でハードコーディング
10
EventFetcher - その2
● EventFetcher.getMapCompletionEvents()
● Map処理結果情報を取得ののちSUCCEEDEDのものを対象にURIや
MapID、ホスト名などの情報を確認
– scheduler.addKnownMapOutput()で情報保存 (L:133)
– addKnownMapOutput()内では、以下の情報を保存
● mapLocations ← Map処理を実行したホスト情報やホスト名
● MapHost.addKnownMap() ← Map処理のTaskAttemptID
● pendingHosts ← Map処理結果を取得するためのホスト情報
– FetcherスレッドでMap処理結果を取得
11
Fetcher - その1
● Fetcher.run() : 無限ループでMap処理結果を取得
● scheduler.getHost()にて、取得するMap処理実行ホスト情報を取得
(L:145)
● copyFromHost()で、Map処理実行ホストより結果取得 (L:149)
● scheduler.freeHost()にて、Map処理実行ホスト情報を戻す (L:152)
– 一つのホストから集中して取得することを防ぐため
12
Fetcher - その2
● ShuffleScheduler.getHost()
● pendingHosts内に複数あるMap処理ホスト情報をランダムに取得
– random.nextInt
– seedは、Ramdom(System.currentTimeMillis())
● pendingHostsはHashSetであるので、順序性を持たないためfor文によ
り対象のMap処理ホスト情報をpickup
13
Fetcher - その3
● copyFromHost()
● scheduler.getMapsForHost()で取得するMap処理結果を決定 (L:172)
– host.getAndClearKnownMaps() で該当ホストのTaskAttemptID
を全て取得、host情報が持つTaskAttemptIDは一旦clear
– TaskAttemptIDリストより、結果を取得していないSUCCEEDであ
るTaskAttemptIDを20個取得 (20個はハードコーディング)
– 21番目以降のTaskAttemptIDは、host.addKnownMap()で戻す
● Map処理を実行したTaskTrackerにHTTPにて接続確立
– URLに20個のMapIDを渡す
● copyMapOutput()で、TaskAttemptIDに沿ったMap処理結果をメモリ
上で保存するかディスクで保存する (L:251)
14
Fetcher - その4
● copyMapOutput() : 取得したTaskAttemptIDによる結果ごとに実行
● header情報取得 (L:282 – L:287)
● merger.reserve()でMap処理結果でメモリで保持するかディスクで保
持するか決定 (L:305)
– メモリ or ディスク の判断は”パラメータ的な話題”で説明
● reserve結果、メモリの場合shuffleToMemory()にてMap処理結果をメ
モリで保持 (L:319), ディスクの場合shuffleToDisk()にてMap処理結果
をローカルディスクに書き出す (L:322)
● scheduler.copySucceeded()で、取得完了に関して処理 (L:322)
– output.commit()で、メモリ/ディスクで保持するMap処理結果数が
閾値を超えた場合、Spill/Mergeを実行
– 閾値については”パラメータ的な話題”で説明
15
ポイント
● 新規Map処理結果は、EventFetcher.getMapCompetionEvents()の呼び出
しで確認できる
● 1回の取得ごとに1秒sleepする (L:72)
– SLEEP_TIMEはハードコーディングされている
● Shuffle.run()内のscheduler.waitUntilDone()で状況を判断する
● 1回の確認で2秒waitする (L:364)
– wait時間はハードコーディングされている
● 0.20系までと比べるとShuffleによる待ち時間は改善されている
16
パラメータ的な話題 - その1
● Fetcherにて、Map処理結果をメモリ or ディスクに書き出す基準
● MergeManager.canShuffleToMemory()
– “Reduce用ヒープサイズ * Copy用領域 * 0.25” よりMap処理結果
(1つ) が小さければメモリ
– Copy用領域 : mapreduce.reduce.shuffle.input.buffer.percent
● デフォルト 0.9
● Map処理結果をcommitするときのメモリ上からSpillする基準
● MergeManager.CloseInMemoryFile()
– “Reduce用ヒープメモリ * Copy用領域 * X” を超えた場合Spill処理
開始
– X : mapreduce.reduce.shuffle.merge.percent
● デフォルト 0.9
17
パラメータ的な話題 - その2
● disk上のMap処理結果(segment)をmergeする基準
● MergeManager.CloseOnDiskFile()
– segment数 > (2 * X – 1) となった場合に開始
– X : mapreduce.task.io.sort.factor
● デフォルト 100
● Fetcher用スレッド(Map処理結果同時取得)数
● mapreduce.reduce.shuffle.parallel.copies
– デフォルト 5
18
終わり
ご静聴ありがとうございました

More Related Content

PPTX
遺伝研スパコンを使った解析の並列化.pptx
PDF
Kansai mrb gr_sakura
PDF
Road to ggplot2再入門
PDF
Fluentd casual
PDF
菩薩でもわかる!Rで動かすExcelアドインの作り方
PDF
Rが苦手な人にもRを使って頂くために~RcommanderとRook~
PDF
WDD2012_SC-004
PDF
RでGPU使ってみた
遺伝研スパコンを使った解析の並列化.pptx
Kansai mrb gr_sakura
Road to ggplot2再入門
Fluentd casual
菩薩でもわかる!Rで動かすExcelアドインの作り方
Rが苦手な人にもRを使って頂くために~RcommanderとRook~
WDD2012_SC-004
RでGPU使ってみた

What's hot (20)

PPT
Hadoop輪読会第6章
PPTX
HUで6000万pvのトラフィックを捌くまでに起ったことをありのままに話すぜ
PDF
20220111 SoftwareDesign #32 kitazaki
ODP
Building production server on docker
PDF
Building production server on docker
PDF
CouchDB JP & BigCouch
PPTX
Stream2の基本
PDF
Slub data structure
PDF
Slub alloc and free
PDF
時を超えた JavaScript の道
KEY
Hadoop splittable-lzo-compression
PDF
20131109 ruby conf2013
PPTX
Ctb57 with god7
PDF
そろそろRStudioの話
PDF
グローバル化はなぜ日時処理問題を引き起こすのか
PDF
Fabric
PDF
Node-v0.12の新機能について
PDF
Ssaw08 0701
PPTX
RelaxCafe@CouchDB break.4
PDF
RでつくるWebアプリ~rApache編~
Hadoop輪読会第6章
HUで6000万pvのトラフィックを捌くまでに起ったことをありのままに話すぜ
20220111 SoftwareDesign #32 kitazaki
Building production server on docker
Building production server on docker
CouchDB JP & BigCouch
Stream2の基本
Slub data structure
Slub alloc and free
時を超えた JavaScript の道
Hadoop splittable-lzo-compression
20131109 ruby conf2013
Ctb57 with god7
そろそろRStudioの話
グローバル化はなぜ日時処理問題を引き起こすのか
Fabric
Node-v0.12の新機能について
Ssaw08 0701
RelaxCafe@CouchDB break.4
RでつくるWebアプリ~rApache編~
Ad

Viewers also liked (8)

PPT
Paseo bosetti
DOC
Sustentación proyecto 4
PPTX
Ingenier%c3%ada de software
PPTX
Herramietas pedagogicas en internet
 
PDF
Ind tam-015-doc
PPTX
Si no usas internet, estas en nada
PPT
Resumen estudio informativo nueva linea castelldefels cornellà-zona universit...
PPT
Trasnpallets
Paseo bosetti
Sustentación proyecto 4
Ingenier%c3%ada de software
Herramietas pedagogicas en internet
 
Ind tam-015-doc
Si no usas internet, estas en nada
Resumen estudio informativo nueva linea castelldefels cornellà-zona universit...
Trasnpallets
Ad

Similar to SourceReading 20101020 (17)

PDF
Hadoop事始め
PDF
Data-Intensive Text Processing with MapReduce(Ch1,Ch2)
PDF
ただいまHadoop勉強中
PPTX
A 2-3ゾウ使いへの第一歩 hadoop on azure 編
PPTX
ゾウ使いへの第一歩
PDF
第1回Hadoop関西勉強会参加レポート
PPTX
〜Apache Geode 入門 gfsh によるクラスター構築・管理
PDF
MapReduce解説
PDF
Hadoop - OSC2010 Tokyo/Spring
PDF
MapReduce/YARNの仕組みを知る
PDF
Kuduを調べてみた #dogenzakalt
PPT
Googleの基盤クローン Hadoopについて
PDF
Twitter クライアント “Termtter” の紹介と収集したソーシャルデータを Fluentd + Hadoop で分析する話
PDF
Hive on Spark を活用した高速データ分析 - Hadoop / Spark Conference Japan 2016
PDF
PPTX
ATN No.1 MapReduceだけでない!? Hadoopとその仲間たち
PDF
Spark shark
Hadoop事始め
Data-Intensive Text Processing with MapReduce(Ch1,Ch2)
ただいまHadoop勉強中
A 2-3ゾウ使いへの第一歩 hadoop on azure 編
ゾウ使いへの第一歩
第1回Hadoop関西勉強会参加レポート
〜Apache Geode 入門 gfsh によるクラスター構築・管理
MapReduce解説
Hadoop - OSC2010 Tokyo/Spring
MapReduce/YARNの仕組みを知る
Kuduを調べてみた #dogenzakalt
Googleの基盤クローン Hadoopについて
Twitter クライアント “Termtter” の紹介と収集したソーシャルデータを Fluentd + Hadoop で分析する話
Hive on Spark を活用した高速データ分析 - Hadoop / Spark Conference Japan 2016
ATN No.1 MapReduceだけでない!? Hadoopとその仲間たち
Spark shark

SourceReading 20101020

  • 2. 2 背景 ● 某案件より:「Reduce処理に時間が掛かりすぎる!」 → リソースネックではなかった → 処理ログを見るとShuffleで延々と時間が掛かる! → これが有名なShuffleのワナね! いきなり大きな壁にぶつかった2年前の秋・・・ 月日は流れ・・・ ● 2010年8月 0.21.0リリース! → ある人曰く:「Shuffleは少々手を入れたぜ!」 → おぉ!これは確認せずにはいられなゐ! といういことで、Shuffleがどうなったか読んでみた。
  • 3. 3 前提 ● Hadoop 0.21.0 ● 対象は、Shuffle時にMap処理結果を取得する部分 ● 大まかな流れのみで詳細や異常系までは読んでいません! ● JobTrackerはlocalモードではないです! ● 読み違いは、ご容赦を!
  • 4. 4 Shuffleへの道のり ● Hadoopの実装では、Map処理やReduce処理はTaskTrackerそのものでは なく、TaskTrackerより生成されるChildが実行 ● Child : org.apache.hadoop.mapred.Child Childは、Map処理やReduce処理を実行する (L:217) ● taskFinal.run()よりReduceTask.run()が実行 ● Hadoopでは、ReduceTask内でShuffleが処理されるの で、ReduceTask.run()を追いかける
  • 5. 5 ReduceTask ● ReduceTask : org.apache.hadoop.mapred.ReduceTask ● ReduceTask内でShuffleインスタンス生成 (L:353) ● Shuffle : org.apache.hadoop.mapreduce.task.reduce – 0.21.0より導入されたクラス – Shuffleコンストラクタ内でShuffleScheduler, MergeManagerイン スタンスを生成 (L:88, L:92) ● Shuffleインスタンスのrun()を実行 (L:362) Combine処理は、 Spillする場合に処理される
  • 6. 6 ShuffleScheduler ● mapLocations : Map<String, MapHost> / HashMap ● pendingHosts : Set<MapHost> / HashSet ● finishedMaps : final boolean[] ● totalMaps : final int ● remainingMaps : int ● copySucceed() : Map処理結果の取得が成功したときに実行 ● addKnownMapOutput() : Map処理結果情報(ホスト名, MapID)を追加 ● getHost() : Map処理ホスト情報取得 ● getMapForHost() : Map処理ホストで実行したMap処理情報取得 ● waitUntilDone() : Map処理結果取得の完了までwait
  • 7. 7 MergeManager ● IntermediateMemoryToMemoryMergerスレッド ● mapreduce.reduce.merge.memtomem.enabled = trueの場合 ● InMemoryMergerスレッド ● 特定の閾値を超えた場合、MemoryMerge → Spill 実行 ● OnDiskMergerスレッド ● DiskでのMerge ● reserve() : Map処理結果取得のためのメモリ確保 ● ディスク or メモリ or null (メモリ上で扱えるがメモリを大量に使用し ている場合) ● canShufflleToMemory() : Memory or Disk ● finalMerge() : Map処理結果を全て取得した後の最後に実行
  • 8. 8 Shuffle ● Shuffle.run()では、2種類のスレッドを生成と起動 ● EventFetcher (L:106) : Map処理の状況を確認する ● Fetcher (L:112) : Map処理結果を取得する,複数のスレッドを生成 – mapreduce.reduce.shuffle.parallel.copiesプロパティで指定 ● デフォルト5 ● 全てのMap処理が完了するまで無限ループ待ち (L:119) ● PROGRESS_FREQUENCY : 2000ミリ秒でハードコーディング
  • 9. 9 EventFetcher – その1 ● EventFetcher.run() : 無限ループでMap処理実行状況を把握 ● getMapCompletionEvents()を呼び出し (L:66) ● ループ内でThread.sleep(SLEEP_TIME)を実行 (L:72) – SLEEP_TIME : 1000ミリ秒でハードコーディング
  • 10. 10 EventFetcher - その2 ● EventFetcher.getMapCompletionEvents() ● Map処理結果情報を取得ののちSUCCEEDEDのものを対象にURIや MapID、ホスト名などの情報を確認 – scheduler.addKnownMapOutput()で情報保存 (L:133) – addKnownMapOutput()内では、以下の情報を保存 ● mapLocations ← Map処理を実行したホスト情報やホスト名 ● MapHost.addKnownMap() ← Map処理のTaskAttemptID ● pendingHosts ← Map処理結果を取得するためのホスト情報 – FetcherスレッドでMap処理結果を取得
  • 11. 11 Fetcher - その1 ● Fetcher.run() : 無限ループでMap処理結果を取得 ● scheduler.getHost()にて、取得するMap処理実行ホスト情報を取得 (L:145) ● copyFromHost()で、Map処理実行ホストより結果取得 (L:149) ● scheduler.freeHost()にて、Map処理実行ホスト情報を戻す (L:152) – 一つのホストから集中して取得することを防ぐため
  • 12. 12 Fetcher - その2 ● ShuffleScheduler.getHost() ● pendingHosts内に複数あるMap処理ホスト情報をランダムに取得 – random.nextInt – seedは、Ramdom(System.currentTimeMillis()) ● pendingHostsはHashSetであるので、順序性を持たないためfor文によ り対象のMap処理ホスト情報をpickup
  • 13. 13 Fetcher - その3 ● copyFromHost() ● scheduler.getMapsForHost()で取得するMap処理結果を決定 (L:172) – host.getAndClearKnownMaps() で該当ホストのTaskAttemptID を全て取得、host情報が持つTaskAttemptIDは一旦clear – TaskAttemptIDリストより、結果を取得していないSUCCEEDであ るTaskAttemptIDを20個取得 (20個はハードコーディング) – 21番目以降のTaskAttemptIDは、host.addKnownMap()で戻す ● Map処理を実行したTaskTrackerにHTTPにて接続確立 – URLに20個のMapIDを渡す ● copyMapOutput()で、TaskAttemptIDに沿ったMap処理結果をメモリ 上で保存するかディスクで保存する (L:251)
  • 14. 14 Fetcher - その4 ● copyMapOutput() : 取得したTaskAttemptIDによる結果ごとに実行 ● header情報取得 (L:282 – L:287) ● merger.reserve()でMap処理結果でメモリで保持するかディスクで保 持するか決定 (L:305) – メモリ or ディスク の判断は”パラメータ的な話題”で説明 ● reserve結果、メモリの場合shuffleToMemory()にてMap処理結果をメ モリで保持 (L:319), ディスクの場合shuffleToDisk()にてMap処理結果 をローカルディスクに書き出す (L:322) ● scheduler.copySucceeded()で、取得完了に関して処理 (L:322) – output.commit()で、メモリ/ディスクで保持するMap処理結果数が 閾値を超えた場合、Spill/Mergeを実行 – 閾値については”パラメータ的な話題”で説明
  • 15. 15 ポイント ● 新規Map処理結果は、EventFetcher.getMapCompetionEvents()の呼び出 しで確認できる ● 1回の取得ごとに1秒sleepする (L:72) – SLEEP_TIMEはハードコーディングされている ● Shuffle.run()内のscheduler.waitUntilDone()で状況を判断する ● 1回の確認で2秒waitする (L:364) – wait時間はハードコーディングされている ● 0.20系までと比べるとShuffleによる待ち時間は改善されている
  • 16. 16 パラメータ的な話題 - その1 ● Fetcherにて、Map処理結果をメモリ or ディスクに書き出す基準 ● MergeManager.canShuffleToMemory() – “Reduce用ヒープサイズ * Copy用領域 * 0.25” よりMap処理結果 (1つ) が小さければメモリ – Copy用領域 : mapreduce.reduce.shuffle.input.buffer.percent ● デフォルト 0.9 ● Map処理結果をcommitするときのメモリ上からSpillする基準 ● MergeManager.CloseInMemoryFile() – “Reduce用ヒープメモリ * Copy用領域 * X” を超えた場合Spill処理 開始 – X : mapreduce.reduce.shuffle.merge.percent ● デフォルト 0.9
  • 17. 17 パラメータ的な話題 - その2 ● disk上のMap処理結果(segment)をmergeする基準 ● MergeManager.CloseOnDiskFile() – segment数 > (2 * X – 1) となった場合に開始 – X : mapreduce.task.io.sort.factor ● デフォルト 100 ● Fetcher用スレッド(Map処理結果同時取得)数 ● mapreduce.reduce.shuffle.parallel.copies – デフォルト 5