Solaris オペレーティングシステムでのスレッドマイクロステートツールの使用 - NetBeans IDE 6.8 チュートリアル
執筆:
Susan Morgan
2009 年 12 月 [リビジョン番号: V6.8--2]
目次
要件
このチュートリアルに従うには、次のソフトウェアが必要です。
必要な NetBeans ソフトウェアのダウンロードとインストールについては、「NetBeans IDE 6.8 のインストール 」および「C/C++/Fortran 向けの NetBeans IDE の構成 」 を参照してください。
はじめに
C/C++/Fortran プラグインを持つ NetBeans IDE 6.8 には、スレッドの実行状態を監視するためのスレッドマイクロステートツールがあります。このツールは、プロジェクトのスレッドの実行時状態の変化についての全体像を表示し、個々のスレッドの状態についての詳細な情報を表示します。コードのデバッグ時に検出されない可能性のある、アプリケーションの実行時の問題を検出できます。
このチュートリアルでは、Solaris 10 または OpenSolaris オペレーティングシステム上で実行中の C/C++ プロジェクトで、スレッドマイクロステートツールを使用する方法について説明します。スレッドマイクロステートツールは Solaris オペレーティングシステムのみでサポートされます。これは、スレッド状態のデータを収集するために、Solaris マイクロステートアカウンティングテクノロジと DTrace ユーティリティーが必要なためです。スレッドマイクロステートツールは、NetBeans プロジェクトを Solaris オペレーティングシステムで実行すると、デフォルトで実行されます。
IDE を Linux、Windows、または MacOS X クライアントで実行し、ネットワーク上で Solaris システムを利用できる場合、Solaris システムをリモート開発ホストとして使用するようにプロジェクトを設定できます。Linux、Windows、または MacOS X で IDE を実行している場合でも、リモート開発でスレッドマイクロステートツールとその他の Solaris ベースのツールを使用できます。リモート開発ホスト上で構築するための設定方法の詳細については、「C/C++ リモート開発のチュートリアル 」を参照してください。
このチュートリアルでは、Solaris SPARC プロセッサベースシステムで実行されるプロジェクトを使用します。SPARC ベースまたは x86 ベースのシステムで実行されている Solaris または OpenSolaris オペレーティングシステム上で、NetBeans IDE 6.8 を実行する場合は、このチュートリアルの手順に従ってください。このチュートリアルで使用されている「Solaris オペレーティングシステム」は、OpenSolaris と Solaris 10 の両方のオペレーティングシステムを指しています。
Solaris マイクロステートアカウンティング
オペレーティングシステムの多くは、CPU クロックの周期ごとに、または一定の時間間隔で、CPU の統計を収集します。Solaris オペレーティングシステムは、マイクロステートアカウンティングというテクノロジを使用して、イベントごとに CPU とスレッドの統計を収集します。各スレッドのアクティビティーが追跡され、スレッドの実行状態が別の状態に移行したときの時刻が記録されます。これらのタイムスタンプを使用して、スレッドが実行、休眠、待機、ブロックなどに費やした時間を確認できます。この手法により、システムに大きなオーバーヘッドをかけずに、精度の高い統計を集めることができます。
マイクロステートアカウンティングの詳細については、Sun のエンジニア Eric Schrock による有用なブログ「Solaris 10 のマイクロステートアカウンティング 」を参照してください。
Solaris 環境をチュートリアル用に設定
スレッドマイクロステートツールを使用するには、NetBeans を実行する際に使用する Solaris ユーザーアカウントに、システムの動作を監視するための DTrace 権限が付与されている必要があります。ユーザーアカウントには、dtrace_user、dtrace_proc、および dtrace_kernel 権限がある必要があります。
Solaris リモート開発ホスト上でプロジェクトを実行している場合は、開発ホストのユーザーアカウントに DTrace 権限を設定する必要があります。
DTrace 権限を確認するには、コマンドプロンプトに次を入力します。
/bin/ppriv $$
アカウントに必要な権限がある場合、ppriv コマンドで次のような結果が返されるはずです。
E: basic,dtrace_kernel,dtrace_proc,dtrace_user
I: basic,dtrace_kernel,dtrace_proc,dtrace_user
P: basic,dtrace_kernel,dtrace_proc,dtrace_user
L: all
「I:」で始まる行は、シェルから起動したプログラムによって継承される権限を指定するため、重要です。必要な継承可能権限がアカウントになく、管理者権限またはシステムへのルートアクセス権もない場合、システム管理者に問い合わせて、dtrace_user、dtrace_proc、および dtrace_kernel 継承可能権限をアカウントに追加します。
管理者権限またはシステムへのルートアクセス権がある場合、次の説明に従って、必要な権限をユーザーアカウントに付与できます。
ユーザーアカウントに必要な DTrace 権限を永久的に付与するには、次の手順に従います。
権限を変更するユーザーアカウントが、システムからログアウトしていることを確認してください。
スーパーユーザー (root) または別の管理者ユーザーでログインします。
コマンドプロンプトに次を入力し、<ユーザー名> を、変更するユーザーアカウント名に置き換えます。
$ usermod -K defaultpriv=basic,dtrace_kernel,dtrace_user,dtrace_proc <ユーザー名>
ユーザーアカウントでログインして NetBeans IDE を起動し、DTrace データプロバイダでプロファイルツールを使用します。
ユーザーアカウントに必要な DTrace 権限を一時的に付与するには、次の手順に従います。
次を入力して、シェルのプロセスのプロセス ID を特定します。
$ echo $$
スーパーユーザー (root) または別の管理者ユーザーになります。
次を入力し、<プロセス ID> を echo コマンドで返されたプロセス ID に置き換えます。
$ ppriv -s I+dtrace_user,dtrace_proc,dtrace_kernel <プロセス ID>
<プロセス ID> で指定してシェルに入力したすべてのコマンドは必要な権限を継承しています。ユーザーアカウントは、このシェルで NetBeans IDE を開始し、スレッドマイクロステートプロファイルツールを使用できます。
チュートリアル用のプロジェクトの作成
スレッドマイクロステートプロファイル機能を調べるため、IDE に含まれている ProfilingDemo サンプルアプリケーションから新規プロジェクトを作成します。
ProfilingDemo アプリケーションは 3 つの段階で実行されます。2 つのタスクをそれぞれ 10 秒間づつ繰り返し実行し、3 種類の方法を使用して興味深いアクティビティーを生成してプロファイルツールに表示します。最初のタスクでデータをファイルに書き込み、次のタスクで計算を行います。2 つのタスクを 1 セットにし、各セットを開発ホスト上で検出された CPU の数と同じ回数実行します。シングルプロセッサシステムの場合、プログラムは 2 つのタスクを 1 回実行します。32 個のコアがある開発用ホストの場合、プログラムは 2 つのタスクを 32 回実行します。タスクのセットを開始するたびに Enter キーを押す必要があります。
ProfilingDemo には、次のような段階があります。
シーケンシャルデモはシングルスレッドで行われ、2 つのタスクを交互に 10 秒間づつ実行します。CPU の数が多いシステムでは、このデモに時間がかかることがあります。これは多数のタスクセットが次々と実行されるからです。
パラレルデモはマルチスレッドで行われ、ファイルへの書き込みタスクと計算タスクが、各スレッドで同時にそれぞれの CPU に対して 1 回行われます。この段階は、マルチコアマシンでシーケンシャルデモを実行する場合よりも時間がかかりません。実行されるタスクの数はシーケンシャルデモと同じですが、それらが同時に行われるためです。ただし、同じデータへアクセスするスレッドの競合を避けることができないため、正しい結果にならないことがあります。
Pthread Mutex デモもマルチスレッドで行われ、ほかのデモ段階と同じように書き込みタスクと計算タスクが実行されます。ただし、このコードでは、複数のスレッドによる特定の関数へのアクセス競合を防ぐため、排他ロックを使用しています。
ProfilingDemo プロジェクトを作成するには、次の手順に従います。
「ファイル」>「新規プロジェクト」を選択して、「新規プロジェクト」ウィザードを開きます。
ウィザードで「サンプル」カテゴリを選択し、「C/C++」サブカテゴリを選択します。
次の図に示すように、「プロファイルのデモ」を選択して「次へ」をクリックします。
プロジェクトの名前と場所を選択できます。ここでは、デフォルトの ProfilingDemo_1 を NetBeansProjects ディレクトリで使用します。
「完了」をクリックしてウィザードを終了し、プロジェクトを作成します。
プロジェクトプロパティーの設定
「プロジェクト」タブの「ProfilingDemo_1」プロジェクトノードを右クリックし、「プロパティー」を選択します。
「カテゴリ」区画で「構築」ノードを選択します。
「ツールコレクション」として「SunStudio_12」を選択し、「適用」をクリックします。
スレッドマイクロステートツールは Sun Studio ツールに依存しないため、GNU ツールコレクションを使用することもできます。
「カテゴリ」パネルで「実行」ノードを選択します。「コンソールタイプ」に「出力ウィンドウ」を選択して、「適用」をクリックします。このチュートリアルで示すように、外部端末のウィンドウではなく IDE の出力ウィンドウにプログラムの出力を表示できます。
「カテゴリ」区画で「プロファイル」ノードを選択します。「実行時にプロファイルインジケータを表示」を選択します。
「プロファイル構成」で、「C/C++ DTrace 拡張」を選択します。
「プロジェクトプロパティー」ダイアログで「了解」をクリックします。
ProfilingDemo プロジェクトの構築と実行
ProfilingDemo プロジェクトノードを右クリックし、「構築」を選択します。
「出力」タブに、次のような構築の結果が表示されます。引数の不一致に関する警告が表示されても、無視してください。
ProfilingDemo プロジェクトノードを右クリックし、「実行」を選択します。
ProfilingDemo プロジェクトの実行中に Enter キーの操作を押すことを求められたときは、その指示に従います。出力は、次のスクリーンショットのようになります。
「実行監視」タブが開き、スレッドマイクロステートツールの動的グラフが表示されます。「C/C++ DTrace 拡張」プロファイル構成で指定したツールがある場合、それらのツールもすべて表示されます。
次のスクリーンショットでは、すべてのツールが表示され、スレッドマイクロステートツールは赤く強調表示されています。
すべてのツールを表示するには、「実行監視」タブの上部の境界線をクリックして上方にドラッグし、「実行監視」タブのサイズを大きくします。右側をドラッグして、タブを横に広げることもできます。
ProfilingDemo プログラムの出力ウィンドウに実行中の処理が表示されます。それを、IDE がツールにグラフィカルに表示しているデータと照合できます。たとえば、プログラムで割り当て中のメモリー量が表示され、計算が実行され、メモリーが開放されます。こうしたプログラムの動作がグラフに反映されるところを確認できます。
「実行監視」ウィンドウのスレッドマイクロステートのグラフは、プログラムのスレッドの概要を示し、プロジェクトの実行中の実行状態の変化を示します。Solaris のマイクロステートアカウンティング機能は、DTrace 機能を使用して、10 個の実行状態のいずれかにある各スレッドの状態について、詳細な情報を提供します。
スレッドマイクロステートツールは、プロジェクトの実行中に作成されたすべてのスレッドの状態の概要情報をグラフィカルに表示します。表示される状態は、休眠中、待機中、ブロック、および実行中の 4 つのみです。これらの状態は、可能性のある 10 個のマイクロステートを簡略化または概略的に表わしたもので、プログラムで実行中のすべてのスレッドの状態の概要を示します。たとえば、「実行中」状態は、ユーザーモードでの実行、システム呼び出しでの実行、ページフォルトでの実行、トラップでの実行など、あらゆる種類の実行状態を表します。
次のスクリーンショットは、プログラムの実行開始時のシーケンシャルデモの部分です。シングルスレッドで交互に実行される 2 つのタスクを示しています。スレッドが休眠中の部分は、ユーザーが Enter キーを押すのをプログラムが待機している箇所です。
「実行監視」ウィンドウの下部に、スクロールバーが表示されます。スクロールバーをクリックして左右にドラッグすると、すべてのプロファイルツールのデータについて、実行時間の開始から終了までを確認することができます。
次のスクリーンショットの 0:42 秒あたりを見ると、プログラムがパラレルデモ段階に移行し、スレッドマイクロステートに表示されるスレッドの数が 3 つになっています。メインスレッドから 2 つの追加スレッドが起動され、各スレッドでそれぞれ 2 つのタスクが同時に実行されます。「待機」状態 (黄色) および「休眠中」状態 (青) に多くの時間が費やされ、「実行中」状態 (緑) にはあまり時間が使われていないことが分かります。パラレルデモ部分で「ブロック」状態 (オレンジ) に使われた時間がないのは、プログラムのこの部分に、スレッドをブロックする mutex ロックなどのスレッド同期手段が実装されていないためです。
次のスクリーンショットの 0:56 秒あたりを見ると、プログラム実行中に最初に発生した「ブロック」マイクロステートがオレンジ色で示されています。この部分は、プログラムが Pthread Mutex デモ段階に移行した箇所に相当します。ここで、各スレッドは相互排他ロックを使用し、特定の時点でほかのスレッドから干渉されることを回避します。各スレッドは、mutex ロックを取得したあと積極的に実行できます。ほかのスレッドが mutex ロックを所有しているときにコードのロックされた部分にアクセスすると、スレッドはブロックされます。相互排他ロックを使用すると、同じデータへのアクセスが重なってスレッドがデータの競合状態になることを防ぎます。
「スレッドの詳細」ボタンをクリックすると、スレッドマイクロステートの詳細な情報が表示されます。
「スレッドの詳細」タブが開き、状態の詳細情報とともに、プログラムで実行されたすべてのスレッドがタイムラインでグラフィカルに表示されます。
「スレッドの詳細」には、プログラムの実行時間全体での各スレッドの状態遷移が示されます。このウィンドウで何ができるか、少し調べてみましょう。
スレッドの色の付いた領域のいずれかにマウスポインタを置くと (クリックはしない)、その特定の時点で行われていることについての詳細を示すポップアップが表示されます。詳細情報には、データの取得時刻や、その時点での各スレッド状態で費やされた時間の割合などがあります。マウスポインタを右側の「概要」領域に移動すると、スレッドの実行全体の割合を示すポップアップが表示されます。
いくつかの設定を変えることで、「スレッドの詳細」ウィンドウに表示される内容を制御できます。
「詳細レベル」をクリックして、表示する詳細のレベルを選択します。「基本」、「モデレート」、「詳細」のオプションがあり、4 個の実行状態を示す簡単な表示と、10 個のマイクロステートを示すもっとも複雑な表示を選択できます。
「表示」リストをクリックして、表示するスレッドの種類を選択します。「終了スレッドのみ」は、プログラム実行中に終了したスレッドのみを表示します。「ライブスレッドのみ」は、まだ終了していないスレッドのみを表示します。「すべてのスレッド」は、ライブスレッドと終了スレッドの両方を表示します。
個々のスレッドをクリックすると、そのスレッドが強調表示されます。次に、Shift キーを押しながらほかのスレッドをクリックして、スレッドを範囲選択します。隣接していないスレッドを複数選択する場合は、Ctrl キーを押しながら目的のスレッドを選択します。目的のスレッドを強調表示したら、右クリックして「選択されたスレッドのみ表示」を選択します。すべてのスレッドを再度表示するには、「表示」リストを使用します。
スレッドを右クリックしてスレッド名を選択し、スレッド名をデフォルトのスレッド名形式「Thread n」から、スレッドによって実行される機能の名前に変更します。
スレッドグラフを拡大して詳細を見たり、マイクロステートデータを見るには、「スレッドの詳細」ウィンドウの左上にあるプラス (+) ボタンをクリックします。グラフを縮小して表示を広げるには、マイナス (-) ボタンをクリックします。「すべての実行を表示」ボタンをクリックすると、「スレッドの詳細」ウィンドウにプロジェクト実行全体のデータが表示され、スクロールする必要がなくなります。ボタンを再度クリックすると、スレッド詳細のスクロール表示に戻ります。
次のスクリーンショットは、拡大した「スレッドの詳細」ウィンドウです。スレッド ID はスレッドのエントリ関数です。「詳細レベル」は「詳細」に設定されています。
「スレッドの詳細」で特定のスポットをクリックすると「スレッド呼び出しスタック」タブが開き、スタックダンプが表示されます。スタックダンプの表示内で、スタックの個々のノードを拡張して、スタック内の呼び出しを表示できます。または、最上位のノードを右クリックして「すべてを展開」を選択すると、その時点で行われている呼び出しをすべて確認できます。
次のスクリーンショットは、実行の終わりに近い 1:03 あたりで、スレッド 5 をクリックした図です。
次のスクリーンショットで、グレー表示されてない mutex_threadfunc などの関数をクリックすると、関数が呼び出された場所のソースファイルが開きます。
「スレッドの詳細」ウィンドウのスレッドをもう一度クリックします。マウスまたはキーボードを使用して、スレッドのタイムラインに沿って移動できます。
マウスで「ナビゲート」を右クリックし、「キャレットを左に移動」を選択して、現在選択しているスレッドの左側にフォーカスを移動します。タイムラインにポイントを設定するには、「ナビゲート」>「キャレットを設定」を選択して、「スレッド呼び出しスタック」の内容を更新します。「スレッド呼び出しスタック」にフォーカスを切り替えるには、「ナビゲート」>「スタックビューに移動」を選択します。
キーボードショートカットを使用して「スレッドの詳細」のスレッドタイムラインを移動するには、次のキーの組み合わせを使用します。
Ctrl- 左矢印キーおよび Ctrl- 右矢印キーで、スレッドのタイムラインを左右にスクロールします。
Ctrl- 下矢印キーで、タイムライン内のポイントを選択すると、そのポイントの「スレッド呼び出しスタック」が更新されます。
Alt- 下矢印キーで、入力を「スレッド呼び出しスタック」ウィンドウにフォーカスします。
「スレッド呼び出しスタック」で矢印キーと Enter キーを使用すると、関数に関連付けられたソースファイルが表示されます。
スレッド状態の定義
Solaris スレッドマイクロステートでの「詳細」レベル表示について、次に説明します。
ユーザー実行中
ユーザーモードでプロセスが費やした時間の割合。
システム実行中
システムモードでプロセスが費やした時間の割合。
その他で実行中
システムトラップなどの処理でプロセスが費やした時間の割合。
テキストページフォルト
テキストページフォルトの処理でプロセスが費やした時間の割合。
データページフォルト
データページフォルトの処理でプロセスが費やした時間の割合。
ブロック
ユーザーロックの待機にプロセスが費やした時間の割合。
休眠中
休眠でプロセスが費やした時間の割合
待機中
CPU の待機でプロセスが費やした時間の割合。
関連項目
実行プロジェクトに関するデータをコンパイルするためにバックグラウンドで使用されている DTrace テクノロジの詳細については、「BigAdmin DTrace ポータル 」を参照してください。
I/O 使用法ツールについては、「Solaris オペレーティングシステムでの C/C++ プロジェクトの I/O プロファイル 」を参照してください。
CPU 使用、スレッド使用、およびメモリー使用の各ツールについては、「C/C++ プロファイルのチュートリアル 」を参照してください。
NetBeans IDE 用のその他の C/C++ チュートリアルについては、「C/C++ アプリケーションの学習 」を参照してください。
まとめ
このチュートリアルでは、スレッドマイクロステートプロファイルツールの次の点について説明しました。
スレッドマイクロステート情報は、Solaris プラットフォームでは、DTrace ユーティリティーを使用して自動的に収集される。
グラフィカルに表示されるプロファイルインジケータは、プロファイル構成を使用して選択できる。
スレッドマイクロステートツールは、C/C++ DTrace 拡張プロファイル構成または独自に作成した構成でのみ表示される。
プロファイル設定は、「プロファイル」カテゴリのプロジェクトプロパティーにある。
「スレッドの詳細」をクリックすると、個々のスレッドの状態について詳細な情報が表示される。
「スレッドの詳細」タブでスレッドをクリックすると、選択したポイントで実行しているすべてのスレッドのスタックダンプが表示される。
スレッドのスタックダンプの関数をクリックすると、関連するソースファイルがエディタに表示される。
Solaris オペレーティングシステムが実行されているシステムをネットワーク上で使用できる場合、Solaris システムをプロジェクトの構築と実行用のリモート開発ホストとして設定することで、Windows または Mac マシンからスレッドマイクロステートツールを使用できる。