めとべや東京 #5で発表してきました
タイトルは「マルチスレッドデザインパターン再考」です。我ながら仰々しいタイトルですが、結局Producer-Consumerパターン最高!みたいな内容になりました*1。でも実際Producer-Consumerパターンはバッチリハマる局面ではなかなか強力です。後述のデモアプリでは半ば無理やり*2使いまくってます。今っぽいProducer-Consumerパターンの書き方についてはTwitterを #めとべや でググるとLINQ星人の人*3がいろいろ呟いているかもしれません。
スライド自体は勢いで書き切りましたが、個人的に今回はデモアプリ(サンプルコード)の実装に全てを懸けてました。GitHubで全て公開してますので、興味のある方はご覧ください。後述の背景からゴミがたんまり残ってます。
https://github.com/atsukanrock/MultithreadDesignPattern
デモアプリは最終的に以下の形になりました。
- WPFの管理者用アプリがWebフロントエンドからのユーザー入力をSignalRで受け取る。
- 収集開始ボタンのクリックでBing Search APIを叩いてBing画像検索をし、検索結果の画像をローカルのテンポラリーフォルダーに収集する。
- 処理開始ボタンのクリックでテンポラリーフォルダー内の画像に画像処理をかけ、画面にどんどん表示していく。
当初(本当)は以下の形を目指していたんですが、Worker Roleのプログラミングに不慣れだったせいでマルチスレッドプログラミングがまともにできず撃沈。近いうちに勉強して修正したいです。
- 2種類のAzure Worker Roleを起動しておく。画像処理をシングルスレッドでするものとマルチスレッドでするもの。それらへの処理リクエストはAzure Queue Storageで行う。
- WPFの管理者用アプリがWebフロントエンドからのユーザー入力をSignalRで受け取る。
- 収集開始ボタンのクリックでBing Search APIを叩いてBing画像検索をし、検索結果の画像をAzure Blob Storageに保存する。
- 処理開始ボタンのクリックで、上記2種類の画像処理Worker Roleへの処理要求メッセージをQueue Storageに保存する。
- Worker RoleはBlob Storageからオリジナル画像を取得して画像処理をし、Blob Storageに処理結果の画像を保存する。1枚終了する度にASP.NET Web APIでWeb Roleに報告する。
- 報告を受けたWeb RoleはSignalRでWPFの管理者用アプリに伝える。
- WPFの管理者用アプリが処理結果の画像をどんどん表示する。
発表中のデモでは画像処理が重すぎて*4途中で見るのを止めてしまいましたが、発表後に確認したらちゃんとマルチスレッド版が2~3倍早くなっていました。
シングルスレッドだと513秒程度かかった*5:
マルチスレッドだと234秒になった!: