特殊化ヒストグラム

このガイドでは、--engine.SpecializationStatisticsオプションの使用方法について説明します。

特殊化ヒストグラムでは、Truffle DSLノードを特別な方法で生成する必要があります。したがって、標準の特殊化ヒストグラム・オプションを使用すると、次のように出力されます:

js --engine.SpecializationStatistics test.js

[engine] Specialization histogram:
No specialization statistics data was collected. Either no node with @Specialization annotations was executed or the interpreter was not compiled with -Atruffle.dsl.GenerateSpecializationStatistics=true e.g as parameter to the javac tool.

エラーのアドバイスに従って、インタプリタを再コンパイルします。mxユーザーの場合、これは次のように単純です:

mx build -c -A-Atruffle.dsl.GenerateSpecializationStatistics=true

再構築後、特殊化統計を使用できます。その間、IDEがソースを自動的に再コンパイルしないようにしてください。このチュートリアルでは、単純なtest.jsスクリプトを使用します:

function test() {
  var array = [42, "", {}, []]

  var globalVar = true;
  for (element of array) {
    globalVar = element;
  }
}
test();

ここで、特殊化統計を有効にする必要があります。この例では、GraalVMのJavaScriptランチャを使用します:

js --experimental-options --engine.SpecializationStatistics test.js

スクリプトの実行後、各クラスのヒストグラムが出力されます。これらのヒストグラムは各ノードの実行の合計によって順序付けられますが、最も頻繁に使用されるノード・クラスが最後に出力されます。

これらは、test.jsの実行時に出力されるヒストグラムの一部です: (ノート: この出力はすでに古くなっている可能性があります。)

 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Name                                                                         Instances          Executions     Executions per instance
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
| JSWriteCurrentFrameSlotNodeGen                                               8 (17%)            18 (12%)        Min=         1 Avg=        2.25 Max=          5  MaxNode= test.js~5-7:76-128
|   doBoolean <boolean>                                                          1 (13%)             1 (6%)         Min=         1 Avg=        1.00 Max=          1  MaxNode= test.js~4:52-71
|   doInt <int>                                                                  1 (13%)             1 (6%)         Min=         1 Avg=        1.00 Max=          1  MaxNode= test.js~5-7:76-128
|   doSafeIntegerInt                                                             0 (0%)              0 (0%)         Min=         0 Avg=        0.00 Max=          0  MaxNode=  -
|   doSafeInteger                                                                0 (0%)              0 (0%)         Min=         0 Avg=        0.00 Max=          0  MaxNode=  -
|   doLong                                                                       0 (0%)              0 (0%)         Min=         0 Avg=        0.00 Max=          0  MaxNode=  -
|   doDouble                                                                     0 (0%)              0 (0%)         Min=         0 Avg=        0.00 Max=          0  MaxNode=  -
|   doObject                                                                     7 (88%)            16 (89%)        Min=         1 Avg=        2.29 Max=          5  MaxNode= test.js~5-7:76-128
|     <DynamicObjectBasic>                                                         6 (86%)            12 (75%)        Min=         1 Avg=        2.00 Max=          5  MaxNode= test.js~5-7:76-128
|     <IteratorRecord>                                                             1 (14%)             1 (6%)         Min=         1 Avg=        1.00 Max=          1  MaxNode= test.js~1-8:16-130
|     <String>                                                                     2 (29%)             2 (13%)        Min=         1 Avg=        1.00 Max=          1  MaxNode= test.js~5-7:76-128
|     <Integer>                                                                    1 (14%)             1 (6%)         Min=         1 Avg=        1.00 Max=          1  MaxNode= test.js~6:105-123
|   --------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   [doBoolean]                                                                  1 (13%)             1 (6%)         Min=         1 Avg=        1.00 Max=          1  MaxNode= test.js~4:52-71
|   [doInt, doObject]                                                            1 (13%)             4 (22%)        Min=         4 Avg=        4.00 Max=          4  MaxNode= test.js~5-7:76-128
|     doInt                                                                        1 (100%)            1 (25%)        Min=         1 Avg=        1.00 Max=          1  MaxNode= test.js~5-7:76-128
|     doObject                                                                     1 (100%)            3 (75%)        Min=         3 Avg=        3.00 Max=          3  MaxNode= test.js~5-7:76-128
|   [doObject]                                                                   6 (75%)            13 (72%)        Min=         1 Avg=        2.17 Max=          5  MaxNode= test.js~5-7:76-128
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Name                                                                         Instances          Executions     Executions per instance
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
| JSReadCurrentFrameSlotNodeGen                                                8 (17%)            25 (17%)        Min=         1 Avg=        3.13 Max=          5  MaxNode= test.js~5-7:76-128
|   doBoolean                                                                    0 (0%)              0 (0%)         Min=         0 Avg=        0.00 Max=          0  MaxNode=  -
|   doInt <no-args>                                                              1 (13%)             1 (4%)         Min=         1 Avg=        1.00 Max=          1  MaxNode= test.js~5:81-87
|   doDouble                                                                     0 (0%)              0 (0%)         Min=         0 Avg=        0.00 Max=          0  MaxNode=  -
|   doObject <no-args>                                                           8 (100%)           24 (96%)        Min=         1 Avg=        3.00 Max=          5  MaxNode= test.js~5-7:76-128
|   doSafeInteger                                                                0 (0%)              0 (0%)         Min=         0 Avg=        0.00 Max=          0  MaxNode=  -
|   --------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   [doInt, doObject]                                                            1 (13%)             4 (16%)        Min=         4 Avg=        4.00 Max=          4  MaxNode= test.js~5:81-87
|     doInt                                                                        1 (100%)            1 (25%)        Min=         1 Avg=        1.00 Max=          1  MaxNode= test.js~5:81-87
|     doObject                                                                     1 (100%)            3 (75%)        Min=         3 Avg=        3.00 Max=          3  MaxNode= test.js~5:81-87
|   [doObject]                                                                   7 (88%)            21 (84%)        Min=         1 Avg=        3.00 Max=          5  MaxNode= test.js~5-7:76-128
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------

このヒストグラムでは、ノード・クラスごとに2つの内部表が出力されています。

1つ目の表は、特殊化と動的な型の組合せをグループ化したものです。たとえば、このヒストグラムでは、ノード・クラスJSWriteCurrentFrameSlotNodeGen8回インスタンス化され、18回実行されました。これは、インスタンス合計の20%で、その実行のすべてのノード実行の11%です。

このスクリプトでは、doBooleandoObjectおよびdoIntという3つの特殊化がインスタンス化されました。doBoolean特殊化は、1回のみインスタンス化されて実行されました。これは、このノード・クラスのすべてのインスタンスの13%およびすべての実行の6%を占めます。doObject特殊化は、DynamicObjectBasicIteratorRecordおよびStringの3つの異なる入力値の組合せを使用して呼び出されました。特殊化と同様に、ノード当たりのこれらの使用回数および実行回数を確認できます。行ごとに、インスタンス当たりの最小、平均および最大実行回数を確認できます。最後の列には、実行回数が最大のインスタンスのソース・セクションが出力されます。

2つ目の表は、ノード・クラスで使用された特殊化の組合せごとにグループ化したものです。

これらの特殊化統計に関する質問を次にいくつか示します:

  1. 特定の特殊化の組合せはほとんど使用されないため、それを削除するか、統合して単一の特殊化にすることはできますか。
  2. さらなる特殊化のメリットを得られる可能性のある、非常に一般的な型の組合せを使用した特殊化はありますか。
  3. どの特殊化の組合せが一般的で、その独自の特殊化に価値はありますか。これは、調査可能なコードの一般的な多相性を示している可能性があります。
  4. 一般的な特殊化とは何ですか。また、その順序は実行回数と一致しますか。最も一般的に使用される特殊化は、ノード・クラスの最初に順序付ける必要があります。これにより、インタプリタのパフォーマンスが向上する可能性があります。
  5. 予期しないインスタンス化された特殊化はありますか。ある場合は、出力されたソース・セクションを使用してさらに調査します。
  6. 頻繁にインスタンス化されるため、メモリー・フットプリント用に最適化する必要がある特殊化はどれですか。
  7. プロファイルにUncachedという名前のノードはありましたか。キャッシュされていないノードが使用されることはめったにありません。それらが頻繁に使用されている場合は、その理由を詳しく調べることをお薦めします。