Skip to content

Commit 31a2970

Browse files
committed
[GR-39024] Add API to access global self time for StructuredGraph.
PullRequest: graal/13623
2 parents 9f42ff3 + ada79c0 commit 31a2970

File tree

3 files changed

+97
-6
lines changed

3 files changed

+97
-6
lines changed

compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompilationWatchDogTest.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,19 @@ public static int snippet(int value) {
6969
return value;
7070
}
7171

72+
/**
73+
* Access to this list is synchronized to avoid a ConcurrentModificationException.
74+
*/
7275
private List<String> events = new ArrayList<>();
7376

7477
private long firstEvent = System.currentTimeMillis();
7578

76-
private void event(String label) {
79+
private synchronized void event(String label) {
7780
long when = System.currentTimeMillis() - firstEvent;
7881
events.add(String.format("after %d ms: %s", when, label));
7982
}
8083

81-
private String eventLog() {
84+
private synchronized String eventLog() {
8285
return events.stream().collect(Collectors.joining(System.lineSeparator()));
8386
}
8487

@@ -138,10 +141,19 @@ public void onStuckCompilation(CompilationWatchDog watchDog, Thread watched, Com
138141
event("start compiling");
139142
return super.getCode(installedCodeOwner, graph, forceCompile, installAsDefault, options);
140143
} finally {
141-
Assert.assertTrue(eventLog(), !longCompilations.isEmpty());
142-
Assert.assertTrue(eventLog(), longCompilations.stream().allMatch(id -> id == compilation));
143-
Assert.assertTrue(eventLog(), !stuckCompilations.isEmpty());
144-
Assert.assertTrue(eventLog(), longCompilations.stream().allMatch(id -> id == compilation));
144+
check(!longCompilations.isEmpty());
145+
check(longCompilations.stream().allMatch(id -> id == compilation));
146+
check(!stuckCompilations.isEmpty());
147+
check(longCompilations.stream().allMatch(id -> id == compilation));
148+
}
149+
}
150+
151+
/**
152+
* Factored out to only fetch the event log if the condition fails.
153+
*/
154+
private void check(boolean condition) {
155+
if (!condition) {
156+
Assert.fail(eventLog());
145157
}
146158
}
147159
}

compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.Iterator;
3333
import java.util.List;
3434
import java.util.Map;
35+
import java.util.Objects;
3536
import java.util.SortedSet;
3637
import java.util.TreeSet;
3738
import java.util.concurrent.atomic.AtomicLong;
@@ -1123,4 +1124,71 @@ public NodeSourcePosition getCallerContext() {
11231124
public OptimizationLog getOptimizationLog() {
11241125
return optimizationLog;
11251126
}
1127+
1128+
/**
1129+
* Implementers of this interface should provide <empf>global</empf> profile-related information
1130+
* about the {@link StructuredGraph} i.e. global profiling information about the
1131+
* <empf>compilation unit</empf>.
1132+
*
1133+
* Unlike the {@link ProfileProvider} which represents the profile in isolation and relating to
1134+
* a single method, implementers of this interface provide data in the context of a global
1135+
* system and relating to a compilation unit (including e.g. inlined methods).
1136+
*/
1137+
public interface GlobalProfileProvider {
1138+
1139+
GlobalProfileProvider DEFAULT = new GlobalProfileProvider() {
1140+
1141+
public static final int DEFAULT_TIME = -1;
1142+
1143+
/**
1144+
* The default time provider always returns -1, i.e. the self time is unknown by
1145+
* default.
1146+
*/
1147+
@Override
1148+
public double getGlobalSelfTimePercent() {
1149+
return DEFAULT_TIME;
1150+
}
1151+
};
1152+
1153+
/**
1154+
* This method provides an approximation of what percentage of run time is spent executing
1155+
* this compilation unit (a.k.a. self time - the time spent executing the compilation unit).
1156+
* Since the value is meant to represent a percentage, this method should return a value
1157+
* between 0 and 1 (inclusive) for {@link StructuredGraph graphs} for which the data is
1158+
* available. If no data is available, this method should return -1 as a way to disambiguate
1159+
* compilation units that are known to have a self time of 0 and compilation units for which
1160+
* the data is not present.
1161+
*
1162+
* This source of this information could, for example, be gathered through profiling the
1163+
* application with a sampling based profiler, or just a heuristic-based estimation.
1164+
*
1165+
* This data can be used for aggressive optimizations, applying more or less optimization
1166+
* budget to individual compilation units based on this estimate of how much run time is
1167+
* spent in that particular compilation unit.
1168+
*
1169+
* @return A value between 0 and 1 If self time data is available, -1 otherwise.
1170+
*/
1171+
double getGlobalSelfTimePercent();
1172+
1173+
}
1174+
1175+
private GlobalProfileProvider globalProfileProvider = GlobalProfileProvider.DEFAULT;
1176+
1177+
/**
1178+
* Set a {@link GlobalProfileProvider global profile provider} for this {@link StructuredGraph
1179+
* graph}.
1180+
*/
1181+
public void setGlobalProfileProvider(GlobalProfileProvider globalProfileProvider) {
1182+
Objects.requireNonNull(globalProfileProvider);
1183+
this.globalProfileProvider = globalProfileProvider;
1184+
}
1185+
1186+
/**
1187+
* See {@link GlobalProfileProvider#getGlobalSelfTimePercent()}.
1188+
*
1189+
* @return The current {@link GlobalProfileProvider#getGlobalSelfTimePercent() global self time}
1190+
*/
1191+
public double getSelfTimePercent() {
1192+
return globalProfileProvider.getGlobalSelfTimePercent();
1193+
}
11261194
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,7 @@ private CompilationResult defaultCompileFunction(DebugContext debug, HostedMetho
11631163

11641164
VMError.guarantee(method.compilationInfo.getCompilationGraph() != null, "The following method is reachable during compilation, but was not seen during Bytecode parsing: %s", method);
11651165
StructuredGraph graph = method.compilationInfo.createGraph(debug, compilationIdentifier, true);
1166+
customizeGraph(graph);
11661167

11671168
GraalError.guarantee(graph.getGraphState().getGuardsStage() == GuardsStage.FIXED_DEOPTS,
11681169
"Hosted compilations must have explicit exceptions [guard stage] %s=%s", graph, graph.getGraphState().getGuardsStage());
@@ -1224,6 +1225,16 @@ private CompilationResult defaultCompileFunction(DebugContext debug, HostedMetho
12241225
}
12251226
}
12261227

1228+
/**
1229+
* Allows subclasses to customize the {@link StructuredGraph graph} after its creation.
1230+
*
1231+
* @param graph A newly created {@link StructuredGraph graph} for one particular compilation
1232+
* unit.
1233+
*/
1234+
protected void customizeGraph(StructuredGraph graph) {
1235+
// Hook for subclasses
1236+
}
1237+
12271238
protected void ensureCalleesCompiled(HostedMethod method, CompileReason reason, CompilationResult result) {
12281239
for (Infopoint infopoint : result.getInfopoints()) {
12291240
if (infopoint instanceof Call) {

0 commit comments

Comments
 (0)