专业化直方图

本指南介绍如何使用 --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
 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------

直方图为每个节点类打印两个内部表格。

第一个表格将专业化和动态类型组合分组在一起。例如,在本直方图中,节点类 JSWriteCurrentFrameSlotNodeGen 被实例化了 8 次,执行了 18 次。这占总实例的 20%,占本次运行所有节点执行的 11%

在本脚本中实例化了三个专业化,分别是 doBooleandoObjectdoIntdoBoolean 专业化只被实例化和执行了一次,占所有实例的 13%,占该节点类所有执行的 6%doObject 专业化使用三个不同的输入值组合进行调用:DynamicObjectBasicIteratorRecordString。与专业化类似,我们可以看到它们使用的次数以及执行的次数。对于每一行,您可以看到每个实例的最小、平均和最大执行次数。最后一列打印实例的最大执行次数的源代码部分。

第二个表格将节点类使用的每个专业化组合分组在一起。

以下是一些您可能想从这些专业化统计数据中获取的答案

  1. 某个专业化组合是否很少使用,可以将其删除/合并成一个专业化吗?
  2. 是否存在一个具有非常常见类型组合的专业化,可以从中受益进一步的专业化吗?
  3. 哪些专业化组合是常见的,值得拥有自己的专业化?这可能表明代码中存在常见的多态性,可以进行研究。
  4. 常见的专业化有哪些,它们的数量是否与执行次数匹配?最常用的专业化应该在节点类中排在首位。这可能会提高解释器的性能。
  5. 是否存在意外实例化的专业化?如果有,请使用打印的源代码部分进一步调查。
  6. 哪些专业化经常被实例化,因此应该优化内存占用?
  7. 配置文件中是否存在名为 Uncached 的节点?未缓存节点的使用应该是很少见的。如果它们被频繁使用,那么值得深入研究一下原因。

联系我们