各イベントのデータには、高精度のタイムスタンプ、スレッド ID、および CPU ID が含まれています。これらを使用すると、パフォーマンスアナライザ内のメトリックを時間、スレッド、または CPU で絞り込むことができます。CPU ID については、getcpuid(2) のマニュアルページを参照してください。getcpuid を利用できないシステムでのプロセッサ ID は -1 であり、Unknown にマップされます。
各イベントでは、共通データ以外に、以降のセクションで説明する固有の raw データが生成されます。これらのセクションではまた、raw データから得られるメトリックの精度と、データ収集がメトリックに及ぼす影響についても説明しています。
クロックプロファイリングのイベント固有のデータは、プロファイリング間隔カウントの配列で構成されています。Oracle Solaris では、間隔カウンタが提供されます。プロファイル間隔の最後で適切な間隔カウンタが 1 増分され、別のプロファイル信号がスケジューリングされます。配列が記録およびリセットされるのは、Solaris スレッドが CPU ユーザーモードに入った場合だけです。配列のリセット時には、ユーザー CPU 状態の配列要素が 1 に設定され、ほかの全状態の配列要素が 0 に設定されます。配列データが記録されるのは、配列がリセットされる前にユーザーモードに入るときです。そのため、この配列には、Solaris スレッドごとにカーネルによって保持されている 10 マイクロステートのそれぞれについて、前回ユーザーモードに入ってから開始されたマイクロステートごとのカウントの累計値が含まれます。Linux オペレーティングシステムでは、マイクロステートは存在しません。唯一の間隔カウンタは「ユーザー CPU 時間」です。
呼び出しスタックは、データと同時に記録されます。プロファイル間隔の最後に Solaris スレッドがユーザーモードになっていない場合は、そのスレッドが再びユーザーモードに入るまで、呼び出しスタックを変更できません。そのため、呼び出しスタックには、各プロファイリング間隔の最後のプログラムカウンタの位置が常に正確に記録されます。
Oracle Solaris で各マイクロステートが関連しているメトリックを表 13 に示します。
|
タイミングデータは統計データとして収集されるため、あらゆる統計的な標本収集手法のすべての誤差の影響を受けます。プログラムの実行時間が非常に短い場合は、少数のプロファイルパケットしか記録されず、多くのリソースを消費するプログラム部分が、呼び出しスタックに反映されないことがあります。このため、目的の関数またはソース行について数百のプロファイルパケットを累積するのに十分な時間または十分な回数で、プログラムを実行するようにしてください。
統計的な標本収集の誤差のほかに、データの収集?関連付け方法、システムにおけるプログラムの実行の進み具合を原因とする誤差もあります。次に示す環境などでは、タイミングメトリックでデータに不正確さやひずみが生じる可能性があります。
スレッドが作成されるとき、最初のプロファイルパケットが記録される前に費やされる時間はプロファイリング間隔より短くなりますが、プロファイリング間隔全体は最初のプロファイルパケット内に記録されるマイクロステートに従います。多数のスレッドが作成された場合、エラーはプロファイル間隔の何倍にもなることがあります。
スレッドが破棄されたとき、一部の時間は、最後のプロファイルパケットが記録されたあとに費やされます。多数のスレッドが破棄された場合、エラーはプロファイル間隔の何倍にもなることがあります。
プロファイル間隔中に、スレッドの再スケジュールが発生する場合があります。その結果、そのスレッドの記録された状態が、プロファイル間隔のほとんどが費やされたマイクロステートを表していない可能性があります。これらのエラーは、スレッドを実行するプロセッサより、実行されるスレッドの方が多い場合にさらに大きくなる可能性があります。
プログラムがシステムクロックと相関関係を持つ形で動作することがあります。この場合は、スレッドが、費やされた時間のごく小さい部分を表しているような状態であると、プロファイリング間隔が常に期限切れになるため、プログラムの特定部分に対して記録された呼び出しスタックは過剰に表されます。マルチプロセッサシステムでは、プロファイリングシグナルによって相互関係が引き起こされる場合があります。プログラムのスレッドを実行中にプロファイリングシグナルによって中断されたプロセッサは、マイクロステートが記録されるときに Trap-CPU マイクロステートにある可能性があります。
カーネルは、プロファイル間隔の時間切れになったときにマイクロステート値を記録します。システムが過負荷状態の場合、この値に、プロセスの本当の状態が反映されないことがあります。Oracle Solaris では、この状況によって、Trap-CPU または Wait-CPU マイクロステートの過剰アカウンティングが発生する可能性があります。
システムクロックが外部ソースと同期されている場合、プロファイルパケット内に記録されるタイムスタンプにはプロファイリング間隔が反映されませんが、クロックに対して行われた調整はすべて含まれます。 システムクロック調整の結果、プロファイルパケットが失われたかのように見える可能性があります。その時間は通常数秒間であり、調整は一定の増分単位で行われます。
動作クロック周波数が動的に変わるマシンで記録された実験には、プロファイリングの不正確さが反映されていることがあります。
今説明した不正確さに加えて、データ収集のプロセスによってタイミングメトリックにひずみが生じます。記録はプロファイリングシグナルによって開始されるため、プロファイルパケットの記録に費やされた時間がプログラムのメトリックに現れることはありません。これは、相関関係の別の例です。記録に費やされたユーザー CPU 時間は、記録されるあらゆるマイクロステート値に配分されます。この結果、ユーザー CPU 時間のメトリックが実際より小さくなり、その他のメトリックが実際より大きくなります。デフォルトのプロファイル間隔の場合、一般に、データの記録に費やされる時間は CPU 時間の 2、3% 未満です。
時間ベースの実験のプロファイリングで得られたタイミングメトリックと、その他の方法で得られた時間を比較する場合は、次の点に注意する必要があります。
シングルスレッドアプリケーションの場合、1 つのプロセスについて記録されたスレッド合計時間は通常、同じプロセスについて gethrtime(3C) によって返された値と比較して数十分の 1 パーセントまで正確です。CPU 時間の場合は、同じプロセスについて gethrvtime(3C) によって返される値と比較して、数パーセント程度異なることがあります。負荷が大きい場合は、差がさらに大きくなることがあります。ただし、CPU 時間の差は体系的なひずみを表しません。さまざまな関数やソース行などについて報告される相対的な時間に大きなひずみは生じません。
パフォーマンスアナライザの報告するスレッド時間は、vmstat が CPU 全体にまたがって集計した時間を報告するため、vmstat の報告する時間とかなり異なることがあります。たとえば、ターゲットプロセスの LWP 数が、そのプロセスが動作するシステムの CPU 数よりも多い場合、アナライザは、vmstat が報告する時間よりもずっと長い待ち時間を報告します。
パフォーマンスアナライザの「統計」ビューや er_print 統計の表示に現れるマイクロステートタイミングは、プロセスファイルシステムの /proc 使用報告に基づいており、マイクロステートで費やされた時間が高い精度で記録されます。詳細は、proc(4) のマニュアルページを参照してください。 これらのタイミングを、全体としてのプログラムを表す <Total> 関数のメトリックと比較することによって、集約されたタイミングメトリックのおよその精度を知ることができます。ただし、「統計」ビューに表示される値には、<Total> のタイミングメトリック値には含まれないその他の関連要素が含まれることがあります。その原因は、データ収集が一時停止される期間によるものです。
ユーザー CPU 時間とハードウェアカウンタサイクル時間は異なります。なぜなら、ハードウェアカウンタは、CPU モードがシステムモードへ切り替えられたときにオフにされるからです。詳細は、トラップを参照してください。
ハードウェアカウンタオーバーフロープロファイリングデータには、カウンタ ID とオーバーフロー値が含まれます。この値は、カウンタがオーバーフローするように設定されている値よりも大きくなることがあります。これは、オーバーフローが発生して、そのイベントが記録されるまでの間に命令が実行されるためです。この値は特に、浮動小数点演算やキャッシュミスなどのカウンタよりも、ずっと頻繁に増分されるサイクルカウンタや命令カウンタの場合に大きくなる可能性があります。イベント記録時の遅延はまた、呼び出しスタックとともに記録されたプログラムカウンタのアドレスが正確にオーバーフローイベントに対応しないことを意味します。詳細は、ハードウェアカウンタオーバーフローの関連付けを参照してください。また、トラップ も参照してください。トラップおよびトラップハンドラは、ユーザーの CPU 時間とサイクルカウンタによって報告される時間の間の、大きな相違の原因になることがあります。
動作クロック周波数が動的に変わるマシンで記録される実験では、サイクルベースのカウントから時間への変換で不正確さが生じることがあります。
収集されるデータ量は、オーバーフロー値に依存します。選択した値が小さすぎると、次のような影響が出ることがあります。
データの収集に費やされる時間が、プログラムの実行時間のかなりの部分を占めることがあります。収集実行では、プログラムの実行ではなく、オーバーフローの処理とデータの書き込みに時間のかなりが費やされる場合があります。
カウントのかなりの部分の原因がデータ収集であることがあります。こうしたカウントは、コレクタ関数 collector_record_counters によるものです。この関数のカウントが大きい場合は、オーバーフロー値が小さすぎます。
データ収集によってプログラムの動作が変わることがあります。たとえば、キャッシュミスのデータの収集では、キャッシュミスの大半が、コレクタの命令のフラッシュとキャッシュからのデータのプロファイリング、プログラム命令とデータとの置き換えによるものです。プログラムで多くのキャッシュミスが発生するように見えますが、データ収集を行わなければ、キャッシュミスが実際にはほとんど発生しなかった可能性があります。
メモリー領域プロファイルは、キャッシュミスなどのメモリー関連イベントが、キャッシュライン、メモリーバンク、ページなどの、マシンの物理的な構造に対して報告されるプロファイルです。
データ領域プロファイルは、これらのメモリー関連イベントが、メモリー関連イベントが発生した命令だけではなく、そのイベントの原因となる参照を行なったデータ構造に対して報告されるプロファイルです。データ領域プロファイリングは、Oracle Solaris を実行している SPARC システム上でのみ使用できます。Oracle Solaris または Linux を実行している x86 システム上ではまだ使用できません。
メモリー領域またはデータ領域のいずれかのプロファイリングの場合、収集されるデータは、メモリーベースのカウンタを使用するハードウェアカウンタである必要があります。正確なカウンタの場合は、SPARC または x86 Oracle Solaris プラットフォームのどちらでも、デフォルトではメモリー領域およびデータ領域データが収集されます。
データ領域プロファイリングをサポートするには、実行可能ファイルを -xhwcprof フラグでコンパイルするようにしてください。このフラグは C、C++、および Fortran コンパイラでのコンパイルに適用できますが、SPARC プラットフォームでのみ意味があります。このフラグはほかのプラットフォームでは無視されます。実行可能ファイルが -xhwcprof でコンパイルされない場合、er_print の data_layout、data_single、および data_objects コマンドではデータが表示されません。メモリー領域プロファイリングでは、正確なカウンタのために -xhwcprof は必要ありません。
実験にデータ領域またはメモリー領域のプロファイルが含まれている場合、er_print ユーティリティーでは、メモリーオブジェクト関連の各種コマンドのほかに、3 つの追加コマンド data_objects、data_single、および data_layout を使用できます。詳細は、データ領域リストを制御するコマンドを参照してください。
さらに、パフォーマンスアナライザにはデータ領域プロファイリングに関連した 2 つのビューや、メモリーオブジェクト用の各種タブが用意されています。「データオブジェクト」ビュー、「データレイアウト」ビュー、および 「メモリーオブジェクト」ビューを参照してください。
ほかの引数なしで collect -h を実行すると、ハードウェアカウンタが一覧表示され、それらが、ロード関係なのか、ストア関係なのか、ロード-ストア関係なのか、および高精度かどうかが示されます。ハードウェアカウンタプロファイリングデータを参照してください。
コレクタは、スレッドライブラリ libthread.so 内の関数の呼び出し、またはリアルタイム拡張ライブラリ librt.so の呼び出しをトレースすることによって、同期遅延イベントを収集します。 イベント固有のデータは、要求と許可 (トレース対象の呼び出しの開始と終了) の高分解能のタイムスタンプと、同期オブジェクト (要求されている相互排他ロックなど) のアドレスで構成されます。スレッド ID と LWP ID は、データが記録された時点での ID です。 待ち時間は、要求時間と許可時間の時間差です。記録されるイベントは、指定したしきい値を要求と許可の時間差が超えたものだけです。同期待ちトレースデータは、許可時に実験ファイルに記録されます。
遅延の原因となったイベントが完了しないかぎり、待ちスレッドがほかの作業を行うことはできません。この待ち時間は、「同期待ち時間」と「ユーザーロック時間」の両方に反映されます。同期遅延しきい値は短時間の遅延を排除するので、「ユーザーロック時間」が「同期待ち時間」よりも大きくなる可能性があります。
待ち時間は、データ収集のオーバーヘッドによってひずみます。そして、このオーバーヘッドは、収集されたイベントの個数に比例します。オーバーヘッドに費やされる待ち時間の一部は、イベント記録のしきい値を大きくすることによって最小化できます。
コレクタは、メモリーの割り当てと割り当て解除の関数である malloc、realloc、memalign、および free に割り込むことによって、これらの関数の呼び出しに関するトレースデータを記録します。メモリーを割り当てるときにこれらの関数を迂回するプログラムの場合、トレースデータは記録されません。別のメカニズムが使用されている Java メモリー管理では、トレースデータは記録されません。
トレース対象の関数は、さまざまなライブラリから読み込まれる可能性があります。パフォーマンスアナライザで表示されるデータは、特定の関数がロードされた元のライブラリに依存することがあります。
短時間で大量のトレース対象関数を呼び出すプログラムの場合、プログラムの実行に要する時間が大幅に長くなることがあります。延びた時間は、トレースデータの記録に使用されます。
コレクタは、標準の I/O ルーチンの呼び出しおよびすべての I/O システムコールに関するトレースデータを記録します。
MPI トレースは、VampirTrace データコレクタの修正版をベースにしています。詳細は、Technische Universitat Dresden の Web サイトにある『VampirTrace User Manual』を検索してください。