質問

私たちのコードベースは数年前のものであり、元の開発者は全員すでにこの世を去っています。非常に多くのスレッドが使用されていますが、明確な設計や共通のアーキテクチャ原則はありません。各開発者は独自のマルチスレッド プログラミング スタイルを持っていたため、キューを使用して相互に通信するスレッド、ミューテックスでデータをロックするスレッド、セマフォでロックするスレッド、プロセス内通信にオペレーティング システムの IPC メカニズムを使用するスレッドがあります。設計ドキュメントはなく、コメントもまばらです。これは混乱しており、コードをリファクタリングしたり、新しい機能を追加しようとするたびに、デッドロックやその他の問題が発生するようです。

それでは、スレッド間のすべてのやり取りを分析して文書化するのに役立つツールやテクニックを知っている人はいますか?FWIW、コードベースは Linux 上の C++ ですが、他の環境用のツールについて知りたいです。


アップデート

これまでに受けた回答に感謝していますが、本質的に「ログメッセージを追加し、何が起こっているのかを把握し、修正する」というアドバイスよりも、より洗練された、または体系的なものを望んでいました。シングルスレッドプログラムでコントロールフローを分析および文書化するためのツールがたくさんあります。マルチスレッドプログラムで利用できるものは何もないのでしょうか?


こちらも参照 マルチスレッドアプリケーションのデバッグ

役に立ちましたか?

解決

Intel のコピーに投資する バーチャルチューン およびそのスレッド プロファイリング ツール。これにより、スレッドの動作をシステム レベルとソース レベルの両方で表示できます。もちろん、物事を自動的に文書化してくれるわけではありませんが、少なくともさまざまな状況で何が起こっているかを視覚化するのには大いに役立つはずです。

体験版もダウンロードできるので、試してみるのも良いかもしれません。私は Windows 版しか使っていませんが、VTune の Web ページを見ると Linux 版もあります。

他のヒント

出発点として、アプリケーション内の戦略的なポイントにトレース ログ メッセージを追加したくなるでしょう。これにより、スレッドを観察する行為によってスレッドの動作が変化する危険を冒さずに、スレッドがどのように対話しているかを分析できます (ステップバイステップのデバッグの場合と同様)。私の経験では .NET プラットフォームを使用しており、私のお気に入りのログ ツールは log4net です。これは無料で、広範な構成オプションがあり、ログの実装方法を賢明に考えていれば、アプリケーションのパフォーマンスを著しく妨げることはありません。あるいは、System.Diagnostics 名前空間には、.NET の組み込み Debug (または Trace) クラスがあります。

問題を引き起こす可能性が最も高い共有メモリ ロック (ミューテックスとセマフォ) に最初に焦点を当てます。どの状態がロックによって保護されているかを確認し、どの状態が複数のロックの保護下にあるかを判断します。これにより、潜在的な競合の可能性が感じられます。ロックを保持しているコードがメソッドを呼び出す状況を見てください (仮想メソッドを忘れないでください)。可能な限り、これらの呼び出しを排除するようにしてください (ロックの保持時間を短縮することによって)。

保持されているミューテックスのリストと、それらが保護する状態の大まかなアイデアを考慮して、ロック順序を割り当てます (つまり、ミューテックス A は常にミューテックス B の前に取得される必要があります)。コード内でこれを強制してみてください。

同時実行性に悪影響が及ばない場合、複数のロックを 1 つに結合できるかどうかを確認してください。たとえば、ミューテックス A と B にデッドロックがある可能性があり、順序付けスキームを簡単に実行できない場合は、最初にそれらを 1 つのロックに結合します。

簡単なことではありませんが、問題に対処するために同時実行性を犠牲にしてコードを簡素化することに私は賛成です。

これは自動ツールにとって非常に難しい問題です。調べてみるとよいでしょう モデルチェック あなたのコード。魔法のような結果を期待しないでください。モデル チェッカーは、効果的にチェックできるコードの量とスレッドの数が非常に限られています。

あなたにとって役に立ちそうなツールは、 チェス (残念ながら Windows のみですが)。 ブラスト これもかなり強力なツールですが、使用するのが非常に難しく、C++ を処理できない場合があります。ウィキペディアにも載ってます 蒸気, 、これまで聞いたことはありませんが、うまくいくかもしれません:

StEAM は C++ 用のモデル チェッカーです。デッドロック、セグメンテーション違反、範囲外の変数、および非終了ループを検出します。

あるいは、少数の明確に定義された (そしてできれば高レベルの) 同期スキームにコードを収束させようとすることは、おそらく非常に役立つでしょう。同じコード ベース内にロック、セマフォ、モニターを混在させると問題が発生します。

log4net または同様のツールを使用する場合に留意すべき点の 1 つは、これらのツールはアプリケーションのタイミングを変更し、根本的な競合状態を隠す可能性があることです。デバッグ用に不適切に書かれたコードがいくつかあり、ロギングを導入したところ、実際に競合状態やデッドロックが解消されました (またはその頻度が大幅に減少しました)。

Java では、特定の種類の一貫性のない同期を検出する FindBugs (静的バイトコード分析用) や、Coverity、JProbe、OptimizeIt などの企業が提供する多数の動的スレッド アナライザーなどの選択肢があります。

UML はここで役に立ちませんか?

コードベースをリバースエンジニアリングすると、 UML, そうすれば、クラス間の関係を示すクラス図を描くことができるはずです。メソッドがスレッドのエントリ ポイントであるクラスから始めて、どのスレッドがどのクラスを使用しているかを確認できます。私の経験に基づいて、 合理的なローズ, 、これはドラッグ アンド ドロップを使用して実現できます。追加されたクラスと以前のクラスの間に関係がない場合、追加されたクラスは、図の開始時に使用したメソッドで開始されたスレッドによって直接使用されません。これにより、各スレッドの役割に関するヒントが得られるはずです。

これにより、共有される「データ オブジェクト」とスレッド固有のオブジェクトも表示されます。

大きなクラス図を描画し、すべての「データ オブジェクト」を削除した場合、コード ベースの結合と凝集が十分でない限り、その図をクラウドとしてレイアウトできるはずです。各クラウドは 1 つのスレッド、またはスレッドのグループです。ひどい。

これで得られるのはパズルの一部だけですが、役に立つかもしれません。あなたのコードベースがあまりにも濁っていたり、「手続き的」すぎたりしないことを祈るばかりですが、その場合は...

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top