【C#開発ノート】メキキバイト-内部実装+マルチスレッドのデバッグ方法 | AI Engineer
メキキバイトソフトウェア開発チーフの和田悟です。私、入社前に、プロダクトの開発環境や技術レベルは、知っておきたい派です。弊社は様々なプロダクトがありますが、私はメキキバイトを作っています。 c#...
https://www.wantedly.com/companies/hutzper/post_articles/925435
メキキバイトソフトウェア開発チーフの和田悟です。
私、入社前に、プロダクトの開発環境や技術レベルは、知っておきたい派です。
弊社は様々なプロダクトがありますが、私はメキキバイトを作っています。
c#の知見高めたい・フツパーの技術が知りたい方は是非お読みくださいませ。
今回の記事では、メキキバイトのマルチスレッドの方針について書いています。
もし前回の記事をお読みでなければ一読をおすすめします。
メキキバイトのマルチスレッドの方針
ロックはなるべくしない。ロックフリー推奨。
Threadは出来るだけRunning以外の状態にしておく
スレッドには必ず名前を付ける
Task.Runと Threadの使い分け
ロック開放待ちになると1つ以上のスレッドを止めてしまいます。できる限りスムーズに処理が完了するように作ったほうが、全てに優しいです。ロックフリーで作れるならロックフリーな実装を心がけています。
メキキバイトの例)ログのシステム
様々なスレッドがログを出力しています。そのときにログを出力する度にロックが掛かると、アプリケーション全体のパフォーマンスが下がってしまいます。
以下のコードを各スレッドから実行しています。
SIA.Logger?.Write(LogCategory.Info, "ログの内容");
ログを出力する時はシングルトンなクラスインスタンスのメンバ変数のConcuretQueueにログの内容を追加して、ロックフリーにしています。
追加されたログを消費するスレッドを1つ立てて、キューを監視して、キューに中身があったら、各出力先にログを送出しています。
ちなみに、このようなスレッドの使い方の事をスレッドデザインパターンではProducer-Consumerパターンと呼びます。
ロックフリーなコンテナはいくつかc#に用意されています。
スレッドが動いている間は、CPUのコアを消費し続けます。なのでできる限りRunning以外の状態にします。(SpinLockが有用シチュエーションは別など例外アリ)
以下のようなスレッドはコアを消費し続けてしまいます。スレッドが止まることをしていません。
while(true)
{
/*処理*/
}
なるべく以下のようにします。
// 例1
while(true)
{
/*処理*/
Thread.Sleep(1); /* sleepしている間 コアを明け渡せる*/
}
// 例2
while(true)
{
/*長い処理*/
resetEvent.wait(); /* waitしている間 コアを明け渡せる */
}
VisualStudioなどデバッグ実行時にスレッドに名前がついていないと、デバッグしずらくなるので、必ず名前を付けています。
以下のように使い分けています。
Task.Run内でwhileが見つかったら、プルリクエストのレビュー時に注意深く監視しています。Task.Run自体がThreadPoolのスレッドを消費して実行されています。スレッドプールのスレッド数には限りがあるので、なるべく単発で終わる処理での利用を心がけています。
次回以降も技術記事書いていくので、気になる方はフォローよろしくお願いします。
次回はメキキバイトの同期オブジェクトなどについて書きます。