このシリーズでは、第1回目のときに、Windows環境での最速の「ファイル書き出し」の手法は何かを検証してみました。今回は、同じWindows環境で複数スレッドを対象としたときの最速の「ファイル書き出し」の手法は何かを検証してみてみたいと思います。特に、複数スレッドを対象とするときは、情報を書き出すファイルもしくはリソースに対して複数のスレッドからの同時アクセスが発生します。このため、各スレッドのアクセス権限の調停をはかるため「排他処理」が必須になります。また、「排他処理」のコストも意外と無視できません。そこで、今回はこの「排他処理」も加味した最速の「ファイル書き出し」の手法を探って行きたいと思います。

検証① 「排他処理」による処理時間の違い

前述の通り、マルチスレッドで動作するコードをDT10を使用してトレースする場合、テストポイントの情報出力先のリソースが一つであれば、必ず排他処理が必要になります。これは情報の出力方式が何であれ全てに当てはまります。排他処理がないとデータの書き込みが保証されず意図しない結果となるケースがあるためです。今回は、まず初めに「排他処理」の処理方式の違いによってどの程度コストに違いが出て来るかを検証してみたいと思います。

今回検証する「排他処理」の種類

今回は次の3種類の排他処理で検証を行いました。

・クリティカルセクション
・セマフォ
・ミューテックス
「排他処理」に掛かる時間の計測方法

DT10には、特定の二つのテストポイントの時間を計測するための機能として、「2点間実行時間レポート」があります。この機能を使用することで「排他処理」に掛かった時間を計測することができます(正確には、3種類の排他処理の相対的な差を求めることができます)。図1のように、テストポイントを連続で二つ挿入し、これらのテストポイントの2点間実行時間を計測します。これを3種類全ての「排他処理」で計測していきます。

図1: 計測対象のコード

基本的に、テストポイントの情報出力処理は図2のような作りになっていますので、データアクセス処理が共通であれば、結果的に2点間実行時間の時間値の差が「排他処理」に掛かった時間の相対的な差ということになります。

図2: 排他処理に掛かるコストの考え方

計測結果

図3は、図2の考え方に基づき、「排他処理」に掛かるコストをDT10の「2点間実行時間レポート」で算出した結果です。これを見るとクリティカルセクションを使用した場合、他のセマフォ、ミューテックスに比べるとコストがかなり低いことが分かります。

図3: 計測結果

検証② 「排他処理」が他のスレッドに与える影響は?

クリティカルセクションに掛かるコストは他のセマフォやミューテックスに比べて小さいことが分かりましたが、クリティカルセクションは排他処理と言っても「他スレッドを止めて自スレッドを優先」する方式となりますので、セマフォ―やミューテックスに比べて少なからず他のスレッドへの影響を与えている可能性があります。そこで、今度はテストポイント内の「排他処理」が他のスレッドに対してどの程度影響を与えるかを検証してみます。

影響度の計測方法

「排他処理」の影響が他のスレッドに対してどれだけ影響を与えるかを計測するため図4のコードを使用します。

図4: 影響度を測るためのスレッド

上側のThreadFuncを同時に30個動作させ、下側のExThreadFunc内のforループの処理がどの程度影響を受けるかを計測します。ExThreadFuncのforループ内の処理の周期を計測するために、DT10の「ステップ周期時間レポート」を使用します。「ステップ周期時間レポート」は、任意のテストポイントの実行周期を計測することができます。ExThreadFunc内のforループ内のテストポイントの周期を計測し、「排他処理」の種類によって周期にどのように影響が出て行くかを見ていきます。ただ、ExThreadFunc内のテストポイントの出力処理内に排他処理を入れてしまうと意味がなくなってしまいますので、ThreadFuncとExThreadFuncで情報出力処理を図5のように分けます。また、情報を書き出すためのリソースも分けておきます。

図5: 出力処理の違い

計測結果

このようにして得られた結果が図6になります。

図6: 計測結果

結果として、クリティカルセクションで「排他処理」を行ったときの方が他の方式に比べて周期時間が大きいため、他のスレッドに与える影響が大きいと言えます。当然と言えば当然ですが、クリティカルセクションは、他のスレッドからしてみれば動きを勝手に止められているということになるため影響は大きくなり、セマフォやミューテックスはOS側が調停するため他のスレッドへの影響が少ないことが分かります。とはいえ、他のスレッドに与える影響は大きいかもしれませんが、総コストを考えるとクリティカルセクションを使用した方法がベストと言えます。

まとめ

いかがでしたでしょうか。
排他処理を実行するスレッドと、その排他処理には関係のないスレッドというふたつの視点から、排他処理のコストや影響についてお分かりいただけたかと思います。極論を言ってしまえば、排他処理は使わずにスレッドごとに情報を書き出すためのリソースを個別で持つのが最速になるのかもしれませんが、PC上のファイルシステムのアクセスするときに、最終的にはOSレベルで排他処理は必要になります。次回はマルチスレッド環境での「データ量」が変わった場合の各方式のコストなどを比較していきたいと思います。
今回のスレッドごとにログデータを出力するファイルを分けるためのドライバのカスタム方法については、弊社技術サポートまでお気軽にお問い合わせください。