59
バッチを Akka Stream で再実装したら100倍速くなった話

バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Embed Size (px)

Citation preview

Page 1: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

バッチを Akka Stream で再実装したら100倍速くなった話

Page 2: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

根来 和輝 TIS 株式会社 生産技術R&D室

Page 3: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

今日話すこと Akka Streams を使ってバッチの処理速度を100倍にした事例

Page 4: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

パフォーマンスに問題を抱えた本番運用されているバッチ処理

Page 5: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

バッチ処理 毎日夜間に、その日の取引情報をCSVファイルに書き出す

Page 6: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

アーキテクチャ

Active Record

Page 7: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

DBから一括で時刻順の取引情報を取得し、一行ずつ処理し、一行ずつファイルへ書き出す

Page 8: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

問題は何か 処理が終わるのが遅い。応急処置でなんとか凌いでいる。

Page 9: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

遅い原因はなにか?

Page 10: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

調査環境として仮想マシンを構築。 本番環境と同じリソースを割り当て。

Page 11: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

調査のシナリオでは100万件のデータを用意

Page 12: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

結果、処理速度は毎秒4件

Page 13: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

100万件処理するのに3日

Page 14: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

ボトルネックはどこか? スワップ領域が大量に消費

0

1000

2000

3000

4000

5000

6000

0:00 0:20 0:40 1:00 1:20 1:40 2:00 2:20 2:40

- - Memory - - Swap

Page 15: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

処理のボトルネック

Page 16: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

メモリを潤沢に用意すれば問題ないのか?

Page 17: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

Page 18: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

調査のシナリオでは100万件のデータを処理

Page 19: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

結果、処理速度は毎秒100件

Page 20: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

100万件処理するのに3時間

Page 21: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

ボトルネックは解消されたのか?メモリ不足は解消

0

1000

2000

3000

4000

5000

6000

7000

0:00 0:05 0:10 0:15 0:20 0:25

- - Memory - - Swap

Page 22: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

使われているCPUコアは1つのみ

Page 23: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

第2のボトルネック

Page 24: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

少しずつデータを取得。処理を並列で行う。ただし、取得したデータの並びは維持。

Page 25: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

DBから時刻順のデータを少しずつ取得。並列で処理。取得した順序で書き出し。

Page 26: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

ここに Akka Streams が使える

Page 27: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

Akka Streams は Reactive Streams の Akka を使った実装

Page 28: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

アーキテクチャ

Streams

Page 29: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

Reactive Streams の Publisher を通じてデータをストリーミングするAPIを提供

Streams

Page 30: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

同期的な入出力と並列処理

Streams

Page 31: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

既存のバッチと同じ結果が得られるように実装。 キャッシュも既存のものと同様に実装。

Page 32: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

実装の構成要素

‣ ‣

Page 33: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

実装※ 説明用に簡略化したコード

Page 34: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

入力、処理、出力、実行

Page 35: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

Page 36: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

Page 37: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

この部分の処理は並列に実行される

Page 38: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

Page 39: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

Page 40: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

調査環境として仮想マシンを構築。 本番環境と同じリソースを割り当て。

Page 41: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

調査のシナリオでは100万件のデータを処理

Page 42: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

結果、処理速度は毎秒1,180件

Page 43: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

100万件処理するのに14分

Page 44: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

ボトルネックは解消されたのか?メモリ不足は発生していない

0

200

400

600

800

1000

1200

1400

1600

1800

2000

0:00 0:00 0:01 0:02 0:03 0:04 0:05 0:05 0:06 0:07 0:08 0:09

- - Memory - - Swap

Page 45: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

CPUの全コアが使われている

Page 46: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

メモリがボトルネックになっていた場合と比較

Page 47: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

CPUがボトルネックになっていた場合と比較

Page 48: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

Page 49: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

バッチを Akka Streams で再実装したら295倍速くなった話

Page 50: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

ハードウェアを変更せずに大幅な性能改善できた。 experimental なので本番環境への適用は注意。

Page 51: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

Page 52: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

ストリームなのにメモリ不足。Slick の streaming API を使ってデータを取得しているのに一括で取得されてしまう。

Page 53: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

MySQL固有の問題解決方法: enableStreamingResults() を設定

Page 54: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

非同期キャッシュ - spray-caching非同期ノンブロッキングでスレッドセーフなキャッシュ

Page 55: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

Page 56: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

Page 57: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

2016年2月2日 7:00PM-10:30PM、場所は西新宿

Page 58: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

Copyright © 2016 TIS Inc. All rights reserved.

2016年2月2日 7:00PM-10:30PM、場所は西新宿

Page 59: バッチを Akka Streams で再実装したら100倍速くなった話 #ScalaMatsuri

THANK YOU