- 适用于 JDK 24 的 GraalVM(最新)
- 适用于 JDK 25 的 GraalVM(早期访问)
- 适用于 JDK 21 的 GraalVM
- 适用于 JDK 17 的 GraalVM
- 存档
- 开发构建
- Truffle 语言实现框架
- Truffle 分支插桩
- 动态对象模型
- 静态对象模型
- 解释器代码的主机优化
- Truffle 函数内联方法
- 分析 Truffle 解释器
- Truffle 互操作 2.0
- 语言实现
- 使用 Truffle 实现新语言
- Truffle 语言和工具迁移到 Java 模块
- Truffle 原生函数接口
- 优化 Truffle 解释器
- 选项
- 栈上替换
- Truffle 字符串指南
- 特化直方图
- 测试 DSL 特化
- 基于多语言 API 的 TCK
- Truffle 编译队列方法
- Truffle 库指南
- Truffle AOT 概述
- Truffle AOT 编译
- 辅助引擎缓存
- Truffle 语言安全点教程
- 单态化
- 拆分算法
- 单态化用例
- 向运行时报告多态特化
特化直方图
本指南解释了如何使用 --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%
。
在此脚本中实例化了三种特化,即 doBoolean
、doObject
和 doInt
。doBoolean
特化只实例化和执行了一次,占该节点类所有实例的 13%
和所有执行的 6%
。doObject
特化通过三种不同的输入值组合被调用:DynamicObjectBasic
、IteratorRecord
和 String
。与特化类似,我们可以看到每个节点被使用和执行的次数。每一行您都可以看到每个实例的最小、平均和最大执行次数。最后一列打印具有最大执行次数的实例的源部分。
第二个表格按节点类使用的特化组合进行分组。
以下是您可能想从这些特化统计中提出的问题
- 某种特化组合是否很少使用,是否可以将其删除/合并为单一特化?
- 是否存在某种具有非常常见类型组合的特化,可以从进一步的特化中受益?
- 哪种特化组合是常见的,并且可能值得拥有自己的特化?这可能表明代码中存在常见的多态性,值得进一步研究。
- 常见的特化有哪些,它们的顺序是否与执行次数匹配?最常用的特化应在节点类中优先排序。这可能有助于提高解释器的性能。
- 是否实例化了意外的特化?如果是,请使用打印的源部分进行进一步调查。
- 哪些特化经常被实例化,因此应该对其内存占用进行优化?
- 在配置文件中是否存在名为
Uncached
的节点?不缓存节点的用量应该很少。如果它们被频繁使用,那么深入探究原因可能是有价值的。