注釈付き逆アセンブリを解釈するのは簡単ではありません。 リーフ PC とは、次に実行する命令のアドレスです。このため、命令の属性メトリックスは、命令の実行待ちに費やされた時間とみなされます。ただし、命令の実行は必ずしも順に行われるわけではなく、呼び出しスタックの記録に遅延があることもあります。注釈付き逆アセンブリコードを利用するには、実験の記録先であるハードウェアと、そのハードウェアが命令を読み込み、実行する方法を理解しておいてください。
次では、注釈付き逆アセンブリコードを解釈する上での問題点をいくつか説明します。
命令は、命令発行グループと呼ばれるグループ単位で読み込まれ、発行されます。グループに含まれる命令は、ハードウェア、命令の種類、すでに実行された命令、およびほかの命令またはレジスタの依存関係によって異なります。その結果、ある命令が常に前の命令と同じクロックで実行され、次に実行される命令として現れない場合、その命令の出現回数は実際よりも少なくなることを意味します。また、呼び出しスタックが記録されるときに、「次」に実行する命令が複数存在する可能性もあります。
命令発行規則はプロセッサの種類ごとに異なり、キャッシュ行内の命令位置合わせに依存します。リンカーはキャッシュ行よりも高い精度による命令位置合わせを強制的に行うので、関連性がないと思える関数を変更すると、異なる命令の位置合わせが生じる可能性があります。位置合わせが異なると、パフォーマンスの向上や劣化が発生することがあります。
次の例では、同じ関数をわずかに異なる状況でコンパイルしてリンクしています。2 つの出力例は、er_print ユーティリティーからの注釈付き逆アセンブリリストを示しています。2 つの例の命令は同じですが、位置合わせが異なっています。
この例の命令位置合わせでは、cmp と bl,a の 2 つの命令を別々のキャッシュ行にマップし、この 2 つの命令の実行待ちに多大な時間が消費されます。
Excl. Incl. User CPU User CPU sec. sec. 1. static int 2. ifunc() 3. { 4. int i; 5. 6. for (i=0; i<10000; i++) <function: ifunc> 0.010 0.010 [ 6] 1066c: clr %o0 0. 0. [ 6] 10670: sethi %hi(0x2400), %o5 0. 0. [ 6] 10674: inc 784, %o5 7. i++; 0. 0. [ 7] 10678: inc 2, %o0 ## 1.360 1.360 [ 7] 1067c: cmp %o0, %o5 ## 1.510 1.510 [ 7] 10680: bl,a 0x1067c 0. 0. [ 7] 10684: inc 2, %o0 0. 0. [ 7] 10688: retl 0. 0. [ 7] 1068c: nop 8. return i; 9. } |
この例の命令位置合わせでは、cmp と bl,a の 2 つの命令を 1 つのキャッシュ行にマップし、この 2 つの命令の内 1 つの命令のみの実行待ちに多大な時間が消費されます。
Excl. Incl. User CPU User CPU sec. sec. 1. static int 2. ifunc() 3. { 4. int i; 5. 6. for (i=0; i<10000; i++) <function: ifunc> 0. 0. [ 6] 10684: clr %o0 0. 0. [ 6] 10688: sethi %hi(0x2400), %o5 0. 0. [ 6] 1068c: inc 784, %o5 7. i++; 0. 0. [ 7] 10690: inc 2, %o0 ## 1.440 1.440 [ 7] 10694: cmp %o0, %o5 0. 0. [ 7] 10698: bl,a 0x10694 0. 0. [ 7] 1069c: inc 2, %o0 0. 0. [ 7] 106a0: retl 0. 0. [ 7] 106a4: nop 8. return i; 9. } |
特定のリーフ PC の示す命令の発行前に遅延があると、そのリーフ PC の出現回数が多くなることがあります。これは、次のケースを初めとして、さまざまな多くの理由で発生する可能性があります。
命令がカーネルにトラップされたときのように、前の命令の実行に時間がかかり、割り込みが不可能な場合。
算術演算命令が必要とするレジスタの内容が前の命令によって設定されていて、その命令がまだ完了していない場合。このような遅延の例としては、たとえば、データキャッシュミスが発生したロード命令があります。
浮動小数点演算命令が、別の浮動小数点演算命令の終了待ちになっている場合。このような状況は、平方根や浮動小数点除算などのパイプライン化が不可能な命令で発生します。
命令を含むメモリーワードが命令キャッシュに含まれていない場合 (I キャッシュミス)。
UltraSPARC ® III プロセッサ上では、ロード命令でキャッシュミスが発生すると、ミスが解決されないかぎり、その後の命令は、読み込み中のデータを使用する命令であるかどうかに関係なく、すべてブロックされます。UltraSPARC II プロセッサの場合には、読み込み中のデータ項目を使用する命令だけがブロックされます。
UltraSPARC プラットフォームでの TLB ミスを除き、オーバーフローにより生成される割り込みの処理に要する時間などのいくつかの理由から、ハードウェアカウンタのオーバーフローイベントの呼び出しスタックは、オーバーフローが発生した時点ではなく命令シーケンスの後ろの方で記録されます。 サイクルおよび発行された命令などの一部のカウンタの場合、この遅延は問題になりません。しかし、キャッシュミスや浮動小数点演算をカウントするようなカウンタの場合は、そのオーバーフローの原因となっているものとは別の命令がメトリックの原因とされます。多くの場合、イベントを発生させた PC は、記録されている PC の数命令前のもので、逆アセンブリリストでその命令を正確に特定できます。ただし、この命令範囲内に分岐先がある場合、イベントを発生させた PC に対 応する命令を見分けることは難しいか、または不可能です。メモリーアクセスイベントをカウントするハードウェアカウンタについて、コレクタはカウンタ名の前に「+」が付いている場合、イベントを発生させた PC を検索します。この方法で記録されたデータは、データ空間プロファイリングをサポートします。詳細は、「データ空間プロファイリング」および 「-h counter_definition_1...[, counter_definition_n]」を参照してください。