Open3
vb.net 非同期平行処理のメモ
やりたいこと
vb.netのwindowsフォームアプリケーションで時間のかかる処理の並列処理化
元々
DBから処理対象の抽出(3万件くらい)→対象一人一人に対応したとあるデータの抽出(For文)
データの抽出は、PG上の処理とDBへの問い合わせをいくらか繰り返し、加工したデータをテーブルへinsertしていく
2~10秒程I/O待ちのあるクエリが一つあるので、3万件相手に直列で行うと処理時間がとても長い
並列処理&非同期にしてみた
Parallelで簡単にできそうだったので。。
Dim targetList as List(Of T)
Await Task.Run(Sub()
Dim result_cnt As Integer = 0
Parallel.ForEach(targetList ,
Sub(行, loopState)
Try
Recommend(行)
Catch ex As Exception
LogTxtBoxAppend($"抽出処理例外:{ex.GetType().Name}({ex.Message})", True)
End Try
SyncLock Thread.CurrentContext
result_cnt += 1
End SyncLock
Invoke(New DeleChangeText(AddressOf changeText), result_cnt)
End Sub)
End Sub)
おおむねこんな感じ
Recommend()の中でなんやかんややってる
サーバー構成がAWSでAPサーバとDBサーバにわかれていて、テスト環境で実行するとAPサーバーのCPU負荷は大したことないが、DBサーバのCPU負荷が100%で振り切って、しばらくするとsqlの実行タイムアウトが大量にかえってきた。。。
調べるとどうやら↓
非常に参考になった。
そこで、この記事にあるTask.WaitAllとExecuteReaderAsyncを使えばいけるかな?とおもったがRecommendの中でI/O待ちが長いExecuteReaderの処理があってこれを非同期にしたところで、I/O待ちのキューが結局多くなってDBサーバが悲鳴をあげるだけだという結論に至ったので、、(実際に検証してないのでわかりません)
とりあえず、テストは4プロセッサなので上限4でやってみたところいい感じに処理がすすんだ。
試しに10に設定したところ、ギリギリ大丈夫なCPU負荷だったのでそもそもキュー数とDBサーバのプロセッサ数は同列に考えるべきではなさそう、たぶん
本番は36プロセッサあるし、処理速度も段違いなので少しずつあげて調整していきたいと思う。
ThreadLocalどこかで使えそうなので、メモ