Oracle® Developer Studio 12.5: パフォーマンスアナライザ

印刷ビューの終了

更新: 2016 年 6 月
 
 

注釈付き逆アセンブリコード

注釈付き逆アセンブリは、関数またはオブジェクトモジュールの命令のアセンブリコードリスト、および各命令に関連付けられたパフォーマンスメトリックを提供します。注釈付き逆アセンブリは複数の方法で表示することができ、どの方法で表示されるかは、行番号のマッピングおよびソースファイルが存在するかどうか、また注釈付き逆アセンブリが要求されている関数のオブジェクトモジュールが既知かどうかによって決まります。

  • オブジェクトモジュールが既知でない場合、パフォーマンスアナライザでは指定された関数の命令だけが逆アセンブルされ、どのソース行も逆アセンブリ内に表示されません。

  • オブジェクトモジュールが既知の場合、オブジェクトモジュール内のすべての関数が逆アセンブルされます。

  • ソースファイルが使用可能であり、かつ行番号データが記録されている場合、パフォーマンスアナライザでは表示の設定に応じて、ソースと逆アセンブリコードがインターリーブされます。

  • コンパイラによってオブジェクトコードに何からの解説が挿入されている場合は、対応する設定が指定されていれば、その解説も逆アセンブリでインターリーブされます。

逆アセンブリコード内の各命令には、次の情報の注釈が付けられます。

  • コンパイラによって報告されたソース行番号

  • 相対アドレス

  • 命令の 16 進表現 (要求があった場合)

  • 命令のアセンブラの ASCII 表現

呼び出しアドレスの解決が可能な場合、それらのアドレスは関数名などのシンボルに変換されます。メトリックは、命令の行に表示されます。対応する設定が指定されている場合は、インターリーブされた任意のソースコードに表示できます。表示可能なメトリック値は、表 14 に示すソースコードの注釈で説明しているとおりです。

複数の場所に #include されるコードの逆アセンブリリストには、コードが #include されるたびに逆アセンブリ命令が 1 回現れます。ソースコードは初回のみインタリーブされ、逆アセンブリコードの繰り返されるブロックはファイルに表示されます。たとえば、inc_body.h と呼ばれるヘッダーで定義されているコードのブロックが inc_bodyinc_entryinc_middle、および inc_exit という名前の 4 つの関数によって #include されている場合、逆アセンブリ命令のブロックは inc_body.h の逆アセンブリリストに 4 回現れますが、ソースコードは逆アセンブリ命令の 4 つのブロックの先頭でのみインターリーブされます。 「ソース」ビューに切り替えると、逆アセンブリコードの繰り返しにそれぞれ対応するインデックス行が表示されます。

インデックス行が「逆アセンブリ」ビューに表示される場合があります。 「ソース」ビューとは異なり、これらのインデックス行を直接ナビゲーションの目的に使用することはできません。インデックス行の直下にある命令のいずれかにカーソルを置いて「ソース」ビューを選択すると、そのインデックス行で参照されているファイルに移動します。

ほかのファイルのコードを #include するファイルでは、ソースコードのインタリーブなしで、インクルードされたコードが逆アセンブリ命令として表示されます。これらの命令のいずれかにカーソルを置いて「ソース」ビューを選択すると、#include されたコードを含むファイルが開かれます。このファイルが表示された状態で「逆アセンブリ」ビューを選択すると、インターリーブされたソースコードとともに逆アセンブリコードが表示されます。

インライン関数の場合はソースコードと逆アセンブリコードをインタリーブできますが、マクロの場合はできません。

コードが最適化されていない場合、各命令の行番号は逐次順であり、ソース行と逆アセンブリされた命令は予想どおりにインタリーブされます。最適化されている場合は、あとの行の命令が前の行の命令よりも前に表示されることがあります。アナライザのインタリーブアルゴリズムでは、命令が行 N にあると表示される場合は、常に、行 N とその行までのすべてのソース行がその命令の前に挿入されます。最適化を行なった結果、制御転送命令とその遅延スロット命令の間にソースコードが現れます。ソース行の N に関連するコンパイラのコメントは、その行の直前に挿入されます。

注釈付き逆アセンブリの解釈

注釈付き逆アセンブリを解釈するのは簡単ではありません。 リーフ PC とは、次に実行する命令のアドレスです。このため、命令の属性メトリックは、命令の実行待ちに費やされた時間とみなされます。ただし、命令が必ずしも順番に実行されるとは限らないため、呼び出しスタックの記録で遅延が発生することもあります。注釈付き逆アセンブリコードを利用するには、実験の記録先であるハードウェアと、そのハードウェアが命令を読み込み、実行する方法を理解しておいてください。

次では、注釈付き逆アセンブリコードを解釈する上での問題点をいくつか説明します。

命令発行時のグループ化

命令は、命令発行グループと呼ばれるグループ単位でロードおよび発行されます。 グループに含まれる命令は、ハードウェア、命令の種類、すでに実行された命令、およびほかの命令またはレジスタの依存関係によって異なります。その結果、ある命令が常に前の命令と同じクロックサイクルで実行され、次に実行される命令として現れない場合、その命令の出現回数は実際よりも少なくなることを意味します。呼び出しスタックが記録されるときに、次に実行するとみなされる命令が複数存在する可能性もあります。

命令発行規則はプロセッサの種類ごとに異なり、キャッシュ行内の命令位置合わせに依存します。リンカーはキャッシュ行より高い精度で命令位置合わせを強制的に行うため、関連がないように見える関数を変更すると、異なる命令位置合わせが生じることがあります。位置合わせが異なると、パフォーマンスの向上や劣化が発生することがあります。

次の例では、同じ関数をわずかに異なる状況でコンパイルしてリンクしています。2 つの出力例は、er_print ユーティリティーからの注釈付き逆アセンブリリストを示しています。2 つの例の命令は同じですが、位置合わせが異なっています。

次の出力例では、命令位置合わせによって、2 つの命令 cmpbl,a が異なるキャッシュ行にマップされています。これらの 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. }

次の出力例では、命令位置合わせによって、2 つの命令 cmpbl,a が同じキャッシュ行にマップされています。これらの命令のどちらかのみ、実行待ちに長い時間がかかっています。

   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 キャッシュミス)。

ハードウェアカウンタオーバーフローの関連付け

一部のプラットフォームおよび precise カウンタでの TLB ミスを除き、ハードウェアカウンタオーバーフローイベントの呼び出しスタックは、オーバーフローが発生した時点よりあとの命令シーケンス内のある時点で記録されます。この遅延は、オーバーフローによって生成された割り込みの処理にかかった時間など、さまざまな原因によって発生します。 サイクルおよび発行された命令などの一部のカウンタの場合、この遅延は問題になりません。しかし、キャッシュミスや浮動小数点演算をカウントするようなカウンタの場合は、そのオーバーフローの原因となっているものとは別の命令がメトリックの原因とされます。

多くの場合、イベントを発生させた PC は記録された PC の数命令前でしかなく、その命令は逆アセンブリリスト内で正確に特定できます。ただし、この命令範囲内に分岐先がある場合、イベントを引き起こした PC に対応する命令を特定することは困難であるか、または不可能です。

precise キーワードでラベル付けされたカウンタを持つプロセッサを備えたシステムでは、バイナリの特殊コンパイルなしでメモリー領域プロファイリングを行うことができます。たとえば、SPARC T4 および M7 プロセッサには、いくつかの precise カウンタがあります。システムでメモリー領域プロファイリングが可能かどうかを調べるには、collect -h コマンドを実行し、precise キーワードを探します。

たとえば、SPARC T7 プロセッサを備えたシステムで次のコマンドを実行すると、使用可能な高精度 raw カウンタが表示されます。

$ collect -h | grep -i precise | grep -v alias
           Counters labeled as precise in the list below will collect memory-space data by default.
    loads      Instr_ld       precise load-store     events 0123 Load Instructions
    stores     Instr_st       precise load-store     events 0123 Store Instructions
    dcm        DC_miss_commit precise load-store     events 0123 L1 D-cache Misses
        use the 'precise' counter:
    Instr_ld                  precise load-store     events 0123
    Instr_st                  precise load-store     events 0123
    Instr_SPR_ring_ops        precise load-store     events 0123
    Instr_atomic              precise load-store     events 0123
    Instr_SW_prefetch         precise load-store     events 0123
    Instr_block_ld_st         precise load-store     events 0123
    DC_miss_L2_L3_hit_commit  precise load-store     events 0123
                              precise load-store     events 0123
                              precise load-store     events 0123
    DC_miss_commit            precise load-store     events 0123