Skip to content

Commit f570c5e

Browse files
committed
address review comments and style fixes
1 parent 61d41ae commit f570c5e

File tree

5 files changed

+60
-38
lines changed

5 files changed

+60
-38
lines changed

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/ReportHotMetricsTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ public static int snippet01(int limit1) {
5959
public void testAbsNegate() {
6060
ByteArrayOutputStream bos = new ByteArrayOutputStream();
6161
try (TTY.Filter ttyFilter = new TTY.Filter(new LogStream(bos))) {
62-
OptionValues opt = new OptionValues(getInitialOptions(), BasePhase.PhaseOptions.ReportHotMetrics, true, BasePhase.PhaseOptions.ReportHotMetricsAfterPhases, "BoxNodeIdentity=*.snippet01");
62+
OptionValues opt = new OptionValues(getInitialOptions(), BasePhase.PhaseOptions.ReportHotMetrics, "*.snippet01", BasePhase.PhaseOptions.ReportHotMetricsAfterPhases,
63+
"BoxNodeIdentity=*.snippet01");
6364
test(opt, "snippet01", 100);
6465
}
6566
// the missing profile

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/CompilationIdentifier.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ public CompilationRequest getRequest() {
7979
*/
8080
String toString(Verbosity verbosity);
8181

82+
/**
83+
* Get a JavaMethod representation of the current compilation.
84+
*/
8285
default JavaMethod asJavaMethod() {
8386
return null;
8487
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/BasePhase.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import jdk.graal.compiler.debug.GraalError;
4848
import jdk.graal.compiler.debug.GraphFilter;
4949
import jdk.graal.compiler.debug.MemUseTrackerKey;
50+
import jdk.graal.compiler.debug.MethodFilter;
5051
import jdk.graal.compiler.debug.TTY;
5152
import jdk.graal.compiler.debug.TimerKey;
5253
import jdk.graal.compiler.graph.Graph;
@@ -207,9 +208,9 @@ public static class PhaseOptions {
207208
@Option(help = "Exclude certain phases from compilation based on the given phase filter(s)." + PhaseFilterKey.HELP, type = OptionType.Debug)
208209
public static final PhaseFilterKey CompilationExcludePhases = new PhaseFilterKey(null, null);
209210
@Option(help = "Report hot metrics after each phase matching the given phase filter(s).", type = OptionType.Debug)
210-
public static final OptionKey<String> ReportHotMetricsAfterPhases = new OptionKey<>(null);;
211+
public static final OptionKey<String> ReportHotMetricsAfterPhases = new OptionKey<>(null);
211212
@Option(help = "Report hot metrics before each phase matching the given phase filter(s).", type = OptionType.Debug)
212-
public static final OptionKey<String> ReportHotMetricsBeforePhases = new OptionKey<String>("HighTierLoweringPhase");
213+
public static final OptionKey<String> ReportHotMetricsBeforePhases = new OptionKey<>("HighTierLoweringPhase");
213214
@Option(help = "Report hot metrics extracted from compiler IR.", type = OptionType.Debug)
214215
public static final OptionKey<String> ReportHotMetrics = new OptionKey<>(null);
215216
// @formatter:on
@@ -461,8 +462,8 @@ public final void apply(final StructuredGraph graph, final C context, final bool
461462
String reportHotMetricsMethodFilter = PhaseOptions.ReportHotMetrics.getValue(options);
462463
boolean logHotMetricsForGraph = false;
463464
if (reportHotMetricsMethodFilter != null) {
464-
jdk.graal.compiler.debug.MethodFilter hotMetricsMethodFilter = null;
465-
hotMetricsMethodFilter = jdk.graal.compiler.debug.MethodFilter.parse(reportHotMetricsMethodFilter);
465+
MethodFilter hotMetricsMethodFilter = null;
466+
hotMetricsMethodFilter = MethodFilter.parse(reportHotMetricsMethodFilter);
466467
logHotMetricsForGraph = graph.method() != null && hotMetricsMethodFilter.matches(graph.method());
467468
if (!logHotMetricsForGraph) {
468469
CompilationIdentifier id = graph.compilationId();

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/ReportHotCodePhase.java

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.util.List;
3030
import java.util.Optional;
3131

32+
import org.graalvm.word.LocationIdentity;
33+
3234
import jdk.graal.compiler.debug.TTY;
3335
import jdk.graal.compiler.graph.Node;
3436
import jdk.graal.compiler.graph.NodeSourcePosition;
@@ -52,6 +54,7 @@
5254
import jdk.graal.compiler.options.Option;
5355
import jdk.graal.compiler.options.OptionKey;
5456
import jdk.graal.compiler.options.OptionType;
57+
import jdk.graal.compiler.options.OptionValues;
5558
import jdk.graal.compiler.phases.BasePhase;
5659
import jdk.graal.compiler.phases.schedule.SchedulePhase;
5760

@@ -77,9 +80,13 @@ public static class Options {
7780
@Option(help = "Dumps the hottest code parts to the Ideal Graph Visualizer (IGV) for further analysis and visualization.", type = OptionType.Debug)
7881
public static final OptionKey<Boolean> ReportHotCodePartsToIGV = new OptionKey<>(false);
7982
@Option(help = "Specifies the debug level for dumping hottest code parts to the Ideal Graph Visualizer (IGV).", type = OptionType.Debug)
80-
public static final OptionKey<Integer> ReportHotCodIGVLevel = new OptionKey<>(1);
83+
public static final OptionKey<Integer> ReportHotCodeIGVLevel = new OptionKey<>(1);
8184
@Option(help = "Specifies the minimum relative frequency for reporting hot code regions.", type = OptionType.Debug)
82-
public static final OptionKey<Double> MinimalFrequencyToReport = new OptionKey<>(1D);
85+
public static final OptionKey<Double> ReportHotCodeMinimalFrequencyToReport = new OptionKey<>(1D);
86+
@Option(help = "Enables printing of informational messages in hot code regions.", type = OptionType.Debug)
87+
public static final OptionKey<Boolean> ReportHotCodeInfos = new OptionKey<>(false);
88+
@Option(help = "Enables printing of warning messages about potential performance issues in hot code regions.", type = OptionType.Debug)
89+
public static final OptionKey<Boolean> ReportHotCodeWarnings = new OptionKey<>(true);
8390
//@formatter:on
8491
}
8592

@@ -178,11 +185,17 @@ private static int getLengthCap(int len, int cap) {
178185
return Math.min(len, cap);
179186
}
180187

181-
private static void info(String format, Object... args) {
188+
private static void info(OptionValues opt, String format, Object... args) {
189+
if (!Options.ReportHotCodeInfos.getValue(opt)) {
190+
return;
191+
}
182192
TTY.printf(INFO_KEY + format, args);
183193
}
184194

185-
private static void warn(String format, Object... args) {
195+
private static void warn(OptionValues opt, String format, Object... args) {
196+
if (!Options.ReportHotCodeWarnings.getValue(opt)) {
197+
return;
198+
}
186199
TTY.printf(WARNING_KEY + format, args);
187200
}
188201

@@ -196,16 +209,15 @@ protected void run(StructuredGraph graph, C c) {
196209
}
197210

198211
CoreProviders context = (CoreProviders) c;
212+
final OptionValues options = graph.getOptions();
199213

200214
SchedulePhase.runWithoutContextOptimizations(graph, SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS, true);
201215
final StructuredGraph.ScheduleResult scheduleResult = graph.getLastSchedule();
202216

203-
final double minimalReportFrequency = Options.MinimalFrequencyToReport.getValue(graph.getOptions());
217+
final double minimalReportFrequency = Options.ReportHotCodeMinimalFrequencyToReport.getValue(graph.getOptions());
204218

205219
final LoopsData ld = context.getLoopsDataProvider().getLoopsData(scheduleResult.getCFG());
206220
final ControlFlowGraph cfg = ld.getCFG();
207-
// report the 3 hottest blocks and the 3 hottest loops and 3 hottest loops by local loop
208-
// frequency
209221
final List<HIRBlock> hottestBlocks = new ArrayList<>();
210222

211223
Collections.addAll(hottestBlocks, cfg.reversePostOrder());
@@ -223,9 +235,9 @@ protected void run(StructuredGraph graph, C c) {
223235
String hottestGlobalBlocksString = String.format("Hottest %s blocks are %s %s %s", getLengthCap(hottestFirstBlocks.size(), REPORT_HOT_FIRST_N), hottestFirstBlocks,
224236
blocksToString(hottestFirstBlocks, BlockToStringMode.BEGIN_NODE),
225237
blocksToString(hottestFirstBlocks, BlockToStringMode.GLOBAL_FREQUENCY));
226-
info("%s\n", hottestGlobalBlocksString);
238+
info(options, "%s%n", hottestGlobalBlocksString);
227239
if (Options.ReportHotCodePartsToIGV.getValue(graph.getOptions())) {
228-
graph.getDebug().dump(Options.ReportHotCodIGVLevel.getValue(graph.getOptions()), graph, hottestGlobalBlocksString);
240+
graph.getDebug().dump(Options.ReportHotCodeIGVLevel.getValue(graph.getOptions()), graph, hottestGlobalBlocksString);
229241
}
230242
}
231243

@@ -234,9 +246,9 @@ protected void run(StructuredGraph graph, C c) {
234246
String hottestLocalLoopString = String.format("Hottest %s local loops are %s %s", getLengthCap(hottestFirstLocalLoops.size(), REPORT_HOT_FIRST_N),
235247
loopBlocksToString(hottestFirstLocalLoops, LoopToStringMode.BLOCK),
236248
loopBlocksToString(hottestFirstLocalLoops, LoopToStringMode.LOCAL_FREQUENCY));
237-
info("%s\n", hottestLocalLoopString);
249+
info(options, "%s%n", hottestLocalLoopString);
238250
if (Options.ReportHotCodePartsToIGV.getValue(graph.getOptions())) {
239-
graph.getDebug().dump(Options.ReportHotCodIGVLevel.getValue(graph.getOptions()), graph, hottestLocalLoopString);
251+
graph.getDebug().dump(Options.ReportHotCodeIGVLevel.getValue(graph.getOptions()), graph, hottestLocalLoopString);
240252
}
241253
}
242254

@@ -245,9 +257,9 @@ protected void run(StructuredGraph graph, C c) {
245257
String hottestGlobalLoopString = String.format("Hottest %s global loops are %s %s", getLengthCap(hottestGlobalLoops.size(), REPORT_HOT_FIRST_N),
246258
loopBlocksToString(hottestFirstGlobalLoops, LoopToStringMode.BLOCK),
247259
loopBlocksToString(hottestFirstGlobalLoops, LoopToStringMode.GLOBAL_FREQUENCY));
248-
info("%s\n", hottestGlobalLoopString);
260+
info(options, "%s%n", hottestGlobalLoopString);
249261
if (Options.ReportHotCodePartsToIGV.getValue(graph.getOptions())) {
250-
graph.getDebug().dump(Options.ReportHotCodIGVLevel.getValue(graph.getOptions()), graph, hottestGlobalLoopString);
262+
graph.getDebug().dump(Options.ReportHotCodeIGVLevel.getValue(graph.getOptions()), graph, hottestGlobalLoopString);
251263
}
252264
}
253265

@@ -281,12 +293,17 @@ protected void run(StructuredGraph graph, C c) {
281293
private static void reportUnknownProfile(Loop l, Node inside, ControlFlowGraph cfg) {
282294
if (inside instanceof IfNode ifNode) {
283295
if (ifNode.profileSource().isUnknown()) {
296+
final OptionValues optionValues = inside.getOptions();
284297
NodeSourcePosition nsp = ifNode.getNodeSourcePosition();
285298
if (nsp == null) {
286-
warn("Unknown profile for %s with f=%s in hot loop %s, NO NODE SOURCE POSITION%n\tPotential Action Item: Determine lack of node source position and profile.%n", ifNode,
299+
warn(optionValues,
300+
"Unknown profile for %s with relativeFrequency=%s in hot loop %s, NO NODE SOURCE POSITION%n\tPotential Action Item: Determine lack of node source position and profile.%n",
301+
ifNode,
287302
cfg.blockFor(inside).getRelativeFrequency(), l);
288303
} else {
289-
warn("Unknown profile for %s with f=%s in hot loop %s, nsp is %n%s%n\tPotential Action Item: Add profile to the top-of-stack source location.%n", ifNode,
304+
warn(optionValues,
305+
"Unknown profile for %s with relativeFrequency=%s in hot loop %s, node source position is %n%s%n\tPotential Action Item: Add profile to the top-of-stack source location.%n",
306+
ifNode,
290307
cfg.blockFor(inside).getRelativeFrequency(), l,
291308
ifNode.getNodeSourcePosition().toString("\t"));
292309
}
@@ -306,14 +323,15 @@ private static void reportInvariantLoopIf(Loop l, Node inside) {
306323
if (inside instanceof IfNode ifNode) {
307324
LogicNode logicNode = ifNode.condition();
308325
if (!l.whole().contains(logicNode)) {
309-
warn("If %s with condition %s is inside loop %s while condition is not%n\tPotential Action Item: Determine why compiler does not unswitch the loop.%n", ifNode, logicNode, l);
326+
warn(logicNode.getOptions(), "If %s with condition %s is inside loop %s while condition is not%n\tPotential Action Item: Determine why compiler does not unswitch the loop.%n", ifNode,
327+
logicNode, l);
310328
}
311329
}
312330
}
313331

314332
/**
315333
* Reports memory kill operations within a specified hot loop that target
316-
* {@link org.graalvm.word.LocationIdentity.AnyLocationIdentity}.
334+
* {@link LocationIdentity#any()}.
317335
* <p>
318336
* A memory kill to {@code AnyLocationIdentity} signifies a write or invalidation that is
319337
* treated as affecting any possible memory location. Such "any" kills prevent the compiler from
@@ -332,10 +350,11 @@ private static void reportMemoryKillANYInLoop(Loop l, Node inside, ControlFlowGr
332350
if (sk.getKilledLocationIdentity().isAny()) {
333351
if (inside instanceof FixedNode) {
334352
// else we don't have a cfg position
335-
warn("Node %s kills any and has relative f=%s in loop %s %n\tPotential Action Item: Determine if operation is required and replace with less intrusive memory effect if possible.%n",
353+
warn(inside.getOptions(),
354+
"Node %s kills any and has relative relativeFrequency=%s in loop %s %n\tPotential Action Item: Determine if operation is required and replace with less intrusive memory effect if possible.%n",
336355
inside, cfg.blockFor(inside).getRelativeFrequency(), l);
337356
} else {
338-
warn("Node %s kills any in loop %s %n", inside, l);
357+
warn(inside.getOptions(), "Node %s kills any in loop %s %n", inside, l);
339358
}
340359
}
341360
}
@@ -347,10 +366,10 @@ private static void reportMemoryKillANYInLoop(Loop l, Node inside, ControlFlowGr
347366
* {@code y} argument is eligible for speculative guard movement.
348367
* <p>
349368
* Speculative guard movement, as described in
350-
* {@link jdk.graal.compiler.loop.phases.SpeculativeGuardMovementPhase.SpeculativeGuardMovement},
351-
* attempts to optimize execution by moving eligible guards outside the loop when safe.
352-
* Typically, such guards should be speculatively optimized and floated before the loop to
353-
* reduce overhead inside hot code regions.
369+
* {@link jdk.graal.compiler.loop.phases.SpeculativeGuardMovementPhase}, attempts to optimize
370+
* execution by moving eligible guards outside the loop when safe. Typically, such guards should
371+
* be speculatively optimized and floated before the loop to reduce overhead inside hot code
372+
* regions.
354373
* </p>
355374
* <p>
356375
* This report helps identify guards that remain inside loops and may represent missed
@@ -379,8 +398,9 @@ private static void reportHotLoopGuardsInside(Node inside, Loop loop) {
379398
}
380399

381400
if (iv != null && limit != null) {
382-
warn("Guard %s condition %s inside loop with iv %s and limit %s%n\tPotential Action Item: Determine why speculative guard movement does not consider them for optimization.%n", inside,
383-
compare, iv, limit);
401+
warn(inside.getOptions(),
402+
"Guard %s condition %s inside loop with iv %s and limit %s%n\tPotential Action Item: Determine why speculative guard movement does not consider them for optimization.%n",
403+
inside, compare, iv, limit);
384404
}
385405
}
386406
}

truffle/docs/Optimizing.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ The most common causes are:
805805
806806
The `--engine.TraceCompilation` option also shows CallTarget invalidations with an `[engine] opt inv.` prefix.
807807
808-
## Debugging Compiler Optimization Potential
808+
## Uncovering Optimization Barriers: Compiler-Level Insights for Truffle Apps
809809
810810
Once you are comfortable profiling Truffle applications and analyzing results (see [Profiling](Profiling.md)), you may reach a point where you wonder, “Why is this benchmark slower than expected?”
811811
After determining that the majority of execution time is spent in compiled code, the next step is a deeper analysis of the generated machine code.
@@ -826,19 +826,16 @@ To enable reporting of these metrics, launch your application with:
826826
```
827827
This prints warnings and hot spots to `stdout` for all compilation units.
828828
829-
To narrow output to specific methods or functions use known method names like:
829+
To narrow the output to specific methods or functions, use known method names like `*wasm-function:5311*`:
830830
```
831831
--vm.Djdk.graal.ReportHotMetrics='*wasm-function:5311*'
832832
```
833-
To improve the quality of the generated data run with node source position tracking `--vm.Djdk.graal.TrackNodeSourcePosition=true`.
833+
To improve the quality of the generated data, run with node source position tracking `--vm.Djdk.graal.TrackNodeSourcePosition=true`.
834834
835835
### Example Output
836836
```
837837
Reporting hot metrics before HighTierLoweringPhase during compilation of wasm-function:5311
838-
[Hot Code Info] Hottest 3 blocks are [B18, B21, B19] BeginNodeIDs=[4951258|LoopBegin, 823|Merge, 707|Begin] GlobalFrequencies=[241.99984874999717, 241.99984874999717, 120.99992437499859]
839-
[Hot Code Info] Hottest 1 local loops are Blocks=[Loop (depth=1) 4951258|LoopBegin] LocalLoopFrequencies=[241.99999999999716]
840-
[Hot Code Info] Hottest 1 global loops are Blocks=[Loop (depth=1) 4951258|LoopBegin] BasicBlockFrequencies=[241.99984874999717]
841-
[Hot Code Warning] Unknown profile for 704|If with f=241.99984874999717 in hot loop Loop (depth=1) 4951258|LoopBegin, nsp is
838+
[Hot Code Warning] Unknown profile for 704|If with f=241.99984874999717 in hot loop Loop (depth=1) 4951258|LoopBegin, node source position is
842839
at org.graalvm.wasm.nodes.WasmFunctionNode.executeBodyFromOffset(WasmFunctionNode.java:363) [bci: 1654]
843840
at org.graalvm.wasm.nodes.WasmFunctionNode.execute(WasmFunctionNode.java:241) [bci: 15]
844841
[...cut for brevity...]
@@ -850,7 +847,7 @@ Reporting hot metrics before HighTierLoweringPhase during compilation of wasm-fu
850847
* “Local frequency” is the number of times the block is executed per loop iteration.
851848
* “Global frequency” is across the entire method. A value of 1 means the basic block executes once per method invocation.
852849
* `[Hot Code Warning]` denotes locations or IR patterns that may inhibit optimization.
853-
* Warnings include, for example, missing profile data in hot paths (e.g., `unknown profile for 704|If …`), which is a common actionable warning.
850+
* Warnings include, for example, missing profile data in hot paths (for example, `unknown profile for 704|If …`), which is a common actionable warning.
854851
855852
Some warnings may be actionable, while others are for informational purposes. If you encounter frequent or unexplained compiler warnings in your hottest methods and are unsure how to proceed, please reach out to the Truffle community via our Slack channels for advice.
856853

0 commit comments

Comments
 (0)