Skip to content

Commit 2f5854d

Browse files
committed
[GR-33110] [GR-32949] [GR-32022] Avoid context initialization locks; Add support for recurring thread local actions; Finish implementation of synthethic context initialization frame.
PullRequest: graal/9542
2 parents 1fde5c4 + e0e5517 commit 2f5854d

File tree

20 files changed

+647
-153
lines changed

20 files changed

+647
-153
lines changed

tools/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ This changelog summarizes major changes between Truffle Tools versions.
44

55
## Version 21.3.0
66
* Reimplemented CPUSampler to use the Truffle language safepoints thus deprecating several API functions.
7+
* Added new option `--engine.SampleContextInitialization` which includes code executed during context initialization in the general sampling profile instead of grouping it into a single entry.
78
* Support for hash interoperability in Insight - no need to use `Truffle::Interop.hash_keys_as_members` anymore
89
* [Cooperative heap dumping](https://www.graalvm.org/tools/javadoc/org/graalvm/tools/insight/heap/package-summary.html) when embedding Insight into Java applications
910

11+
1012
## Version 21.1.0
1113

1214
* Use `--heap.dump=/path/to/file/to/generate.hprof` to enable [Heap Dumping via Insight](docs/Insight-Manual.md#Heap-Dumping)

tools/src/com.oracle.truffle.tools.profiler.test/src/com/oracle/truffle/tools/profiler/test/CPUSamplerTest.java

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,34 +24,118 @@
2424
*/
2525
package com.oracle.truffle.tools.profiler.test;
2626

27+
import static org.junit.Assert.assertEquals;
28+
29+
import java.util.ArrayList;
2730
import java.util.Collection;
2831
import java.util.Iterator;
32+
import java.util.List;
2933
import java.util.Map;
3034
import java.util.concurrent.atomic.AtomicBoolean;
3135
import java.util.concurrent.atomic.AtomicInteger;
36+
import java.util.function.Predicate;
3237

3338
import org.graalvm.polyglot.Source;
3439
import org.junit.Assert;
3540
import org.junit.Before;
3641
import org.junit.Ignore;
3742
import org.junit.Test;
3843

44+
import com.oracle.truffle.api.TruffleContext;
45+
import com.oracle.truffle.api.TruffleSafepoint;
46+
import com.oracle.truffle.api.nodes.RootNode;
3947
import com.oracle.truffle.api.source.SourceSection;
48+
import com.oracle.truffle.api.test.polyglot.ProxyLanguage;
4049
import com.oracle.truffle.tools.profiler.CPUSampler;
50+
import com.oracle.truffle.tools.profiler.CPUSampler.Payload;
51+
import com.oracle.truffle.tools.profiler.CPUSamplerData;
4152
import com.oracle.truffle.tools.profiler.ProfilerNode;
4253

4354
public class CPUSamplerTest extends AbstractProfilerTest {
4455

45-
private static CPUSampler sampler;
56+
private CPUSampler sampler;
4657

4758
final int executionCount = 10;
4859

4960
@Before
5061
public void setupSampler() {
5162
sampler = CPUSampler.find(context.getEngine());
5263
Assert.assertNotNull(sampler);
53-
synchronized (sampler) {
54-
sampler.setGatherSelfHitTimes(true);
64+
sampler.setGatherSelfHitTimes(true);
65+
}
66+
67+
@Test
68+
public void testInitializeContext() {
69+
RootNode dummy = RootNode.createConstantNode(42);
70+
71+
ProxyLanguage.setDelegate(new ProxyLanguage() {
72+
@Override
73+
protected void initializeContext(LanguageContext c) throws Exception {
74+
for (int i = 0; i < 50; i++) {
75+
Thread.sleep(1);
76+
TruffleSafepoint.pollHere(dummy);
77+
}
78+
}
79+
});
80+
81+
sampler.setPeriod(1);
82+
sampler.clearData();
83+
sampler.setCollecting(true);
84+
context.initialize(ProxyLanguage.ID);
85+
sampler.setCollecting(false);
86+
87+
Map<TruffleContext, CPUSamplerData> data = sampler.getData();
88+
assertEquals(1, data.size());
89+
90+
assertEquals(1, searchInitializeContext(data).size());
91+
}
92+
93+
@Test
94+
public void testSampleContextInitialization() {
95+
RootNode dummy = RootNode.createConstantNode(42);
96+
97+
ProxyLanguage.setDelegate(new ProxyLanguage() {
98+
@Override
99+
protected void initializeContext(LanguageContext c) throws Exception {
100+
for (int i = 0; i < 50; i++) {
101+
Thread.sleep(1);
102+
TruffleSafepoint.pollHere(dummy);
103+
}
104+
}
105+
});
106+
107+
sampler.setPeriod(1);
108+
sampler.setSampleContextInitialization(true);
109+
sampler.setCollecting(true);
110+
context.initialize(ProxyLanguage.ID);
111+
sampler.setCollecting(false);
112+
113+
Map<TruffleContext, CPUSamplerData> data = sampler.getData();
114+
assertEquals(1, data.size());
115+
116+
assertEquals(0, searchInitializeContext(data).size());
117+
}
118+
119+
private static List<ProfilerNode<Payload>> searchInitializeContext(Map<TruffleContext, CPUSamplerData> data) {
120+
List<ProfilerNode<Payload>> found = new ArrayList<>();
121+
for (CPUSamplerData d : data.values()) {
122+
Map<Thread, Collection<ProfilerNode<Payload>>> threadData = d.getThreadData();
123+
assertEquals(threadData.toString(), 1, threadData.size());
124+
125+
searchNodes(found, threadData.values().iterator().next(), (node) -> {
126+
return node.getRootName().equals("<<" + ProxyLanguage.ID + ":initializeContext>>");
127+
});
128+
129+
}
130+
return found;
131+
}
132+
133+
private static void searchNodes(List<ProfilerNode<CPUSampler.Payload>> results, Collection<ProfilerNode<CPUSampler.Payload>> data, Predicate<ProfilerNode<CPUSampler.Payload>> predicate) {
134+
for (ProfilerNode<CPUSampler.Payload> node : data) {
135+
if (predicate.test(node)) {
136+
results.add(node);
137+
}
138+
searchNodes(results, node.getChildren(), predicate);
55139
}
56140
}
57141

tools/src/com.oracle.truffle.tools.profiler/snapshot.sigtest

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ supr java.lang.Object
168168
hfds children,parent,payload,sourceLocation
169169

170170
CLSS public final com.oracle.truffle.tools.profiler.StackTraceEntry
171-
cons public init(java.lang.String)
172171
meth public boolean equals(java.lang.Object)
173172
meth public boolean isCompiled()
174173
meth public boolean isInlined()

tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/CPUSampler.java

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ public CPUSampler create(Env env) {
122122
private long period = 10;
123123
private long delay = 0;
124124
private int stackLimit = 10000;
125+
private boolean sampleContextInitialization = false;
125126
private SourceSectionFilter filter = DEFAULT_FILTER;
126127
private Timer samplerThread;
127128
private SamplingTimerTask samplerTask;
@@ -140,40 +141,42 @@ public void onContextCreated(TruffleContext context) {
140141
}
141142
}
142143

144+
@Override
143145
public void onLanguageContextCreate(TruffleContext context, LanguageInfo language) {
144-
// TODO GR-32022 push and sample synthetic frame
146+
// no code is allowed to run during context creation
145147
}
146148

147149
@Override
148150
public void onLanguageContextCreated(TruffleContext context, LanguageInfo language) {
149-
// TODO GR-32022 push/pop and sample synthetic frame
151+
// no code is allowed to run during context creation
150152
}
151153

154+
@Override
152155
public void onLanguageContextCreateFailed(TruffleContext context, LanguageInfo language) {
153-
// TODO GR-32022 push/pop and sample synthetic frame
156+
// no code is allowed to run during context creation
154157
}
155158

159+
@Override
156160
public void onLanguageContextInitialize(TruffleContext context, LanguageInfo language) {
157-
// TODO GR-32022 push/pop and sample synthetic frame
161+
safepointStackSampler.pushSyntheticFrame(language, "initializeContext");
158162
}
159163

160164
@Override
161165
public void onLanguageContextInitialized(TruffleContext context, LanguageInfo language) {
162-
// TODO GR-32022 push/pop and sample synthetic frame
166+
safepointStackSampler.popSyntheticFrame();
163167
}
164168

169+
@Override
165170
public void onLanguageContextInitializeFailed(TruffleContext context, LanguageInfo language) {
166-
// TODO GR-32022 push/pop and sample synthetic frame
171+
safepointStackSampler.popSyntheticFrame();
167172
}
168173

169174
@Override
170175
public void onLanguageContextFinalized(TruffleContext context, LanguageInfo language) {
171-
// TODO GR-32022 push/pop and sample synthetic frame
172176
}
173177

174178
@Override
175179
public void onLanguageContextDisposed(TruffleContext context, LanguageInfo language) {
176-
// TODO GR-32022 push/pop and sample synthetic frame
177180
}
178181

179182
@Override
@@ -302,6 +305,21 @@ public synchronized void setDelaySamplingUntilNonInternalLangInit(boolean delayS
302305
// Deprecated, a noop.
303306
}
304307

308+
/**
309+
* Enables or disables the sampling of the time spent during context initialization. If
310+
* <code>true</code> code executed during context initialization is included in the general
311+
* profile instead of grouping it into a single entry by default. If <code>false</code> a single
312+
* entry will be created that contains all time spent in initialization. This can be useful to
313+
* avoid polluting the general application profile with sampled stack frames that only run
314+
* during initialization.
315+
*
316+
* @since 21.3
317+
*/
318+
public synchronized void setSampleContextInitialization(boolean enabled) {
319+
enterChangeConfig();
320+
this.sampleContextInitialization = enabled;
321+
}
322+
305323
/**
306324
* @return The filter describing which part of the source code to sample
307325
* @since 0.30
@@ -491,7 +509,7 @@ public Map<Thread, List<StackTraceEntry>> takeSample() {
491509
}
492510
TruffleContext context = activeContexts.keySet().iterator().next();
493511
Map<Thread, List<StackTraceEntry>> stacks = new HashMap<>();
494-
List<StackSample> sample = safepointStackSampler.sample(env, context, activeContexts.get(context));
512+
List<StackSample> sample = safepointStackSampler.sample(env, context, activeContexts.get(context), !sampleContextInitialization);
495513
for (StackSample stackSample : sample) {
496514
stacks.put(stackSample.thread, stackSample.stack);
497515
}
@@ -665,7 +683,7 @@ public void run() {
665683
if (context.isClosed()) {
666684
continue;
667685
}
668-
List<StackSample> samples = safepointStackSampler.sample(env, context, activeContexts.get(context));
686+
List<StackSample> samples = safepointStackSampler.sample(env, context, activeContexts.get(context), !sampleContextInitialization);
669687
synchronized (CPUSampler.this) {
670688
if (!collecting) {
671689
return;

0 commit comments

Comments
 (0)