Skip to content

Commit 9db4278

Browse files
committed
Show compiled and interpreter time in GraalVM sampler
1 parent d2a93bf commit 9db4278

File tree

7 files changed

+148
-27
lines changed

7 files changed

+148
-27
lines changed

visualvm/sampler.truffle/libsrc/com/oracle/truffle/tools/profiler/CPUSampler.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,13 @@ public void setDelaySamplingUntilNonInternalLangInit(boolean b) {
5050
public Map<Thread, List<StackTraceEntry>> takeSample() {
5151
return null;
5252
}
53+
54+
public synchronized void setMode(Mode mode) {
55+
}
56+
57+
public enum Mode {
58+
EXCLUDE_INLINED_ROOTS,
59+
ROOTS,
60+
STATEMENTS
61+
}
5362
}

visualvm/sampler.truffle/libsrc/com/oracle/truffle/tools/profiler/StackTraceEntry.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,7 @@
3838
public class StackTraceEntry {
3939

4040
public StackTraceElement toStackTraceElement() {return null;}
41+
public boolean isCompiled() {return false;}
42+
public boolean isInlined() {return false;}
43+
4144
}

visualvm/sampler.truffle/libsrc/org/graalvm/visualvm/sampler/truffle/stagent/Truffle.java

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import com.oracle.truffle.api.nodes.LanguageInfo;
2828
import com.oracle.truffle.tools.profiler.CPUSampler;
29+
import com.oracle.truffle.tools.profiler.CPUSampler.Mode;
2930
import com.oracle.truffle.tools.profiler.HeapMonitor;
3031
import com.oracle.truffle.tools.profiler.HeapSummary;
3132
import com.oracle.truffle.tools.profiler.StackTraceEntry;
@@ -57,6 +58,7 @@ public class Truffle implements TruffleMBean {
5758
private Method Engine_findActiveEngines;
5859
private Map engines;
5960
private Unsafe unsafe;
61+
private boolean trackFlags;
6062

6163
public Truffle(Unsafe u) {
6264
unsafe = u;
@@ -94,10 +96,13 @@ public Map<String, Object>[] dumpAllThreads() {
9496
Thread t = entry.getKey();
9597
long tid = t.getId();
9698
long threadCpuTime = threadBean.getThreadCpuTime(tid);
97-
StackTraceElement[] stack = getStackTraceElements(entry.getValue());
99+
TruffleStackTrace stack = getStackTraceElements(entry.getValue());
98100
String name = t.getName();
99101
Map<String, Object> threadInfo = new HashMap();
100-
threadInfo.put("stack", stack);
102+
threadInfo.put("stack", stack.stack);
103+
if (trackFlags) {
104+
threadInfo.put("flags", stack.flags);
105+
}
101106
threadInfo.put("name", name);
102107
threadInfo.put("tid", tid);
103108
threadInfo.put("threadCpuTime", threadCpuTime);
@@ -217,13 +222,23 @@ private Collection<CPUSampler> getAllStackTracesInstances() {
217222
return allInstances;
218223
}
219224

220-
private StackTraceElement[] getStackTraceElements(List<StackTraceEntry> entries) {
225+
private static final int COMPILED = 1; // 0001
226+
private static final int INLINED = 2; // 0010
227+
228+
private TruffleStackTrace getStackTraceElements(List<StackTraceEntry> entries) {
221229
StackTraceElement[] stack = new StackTraceElement[entries.size()];
230+
byte[] flags = new byte[entries.size()];
222231

223232
for (int i = 0; i < entries.size(); i++) {
224-
stack[i] = entries.get(i).toStackTraceElement();
233+
StackTraceEntry entry = entries.get(i);
234+
stack[i] = entry.toStackTraceElement();
235+
flags[i] |= entry.isCompiled() ? COMPILED:0;
236+
flags[i] |= entry.isInlined() ? INLINED:0;
237+
if (flags[i] != 0) {
238+
System.err.println(stack[i]+" "+Integer.toHexString(flags[i])+" "+entry.isInlined());
239+
}
225240
}
226-
return stack;
241+
return new TruffleStackTrace(stack, flags);
227242
}
228243

229244
@Override
@@ -297,4 +312,42 @@ private String getLanguageId(Object lang) throws NoSuchFieldException, SecurityE
297312
String lId = (String) unsafe.getObject(lang, unsafe.objectFieldOffset(f));
298313
return lId;
299314
}
315+
316+
@Override
317+
public void setTrackFlags(boolean trackFlags) {
318+
this.trackFlags = trackFlags;
319+
}
320+
321+
@Override
322+
public void setMode(String modeStr) {
323+
if ("ROOTS".equals(modeStr)) {
324+
setMode(Mode.ROOTS);
325+
} else if ("EXCLUDE_INLINED_ROOTS".equals(modeStr)) {
326+
setMode(Mode.STATEMENTS);
327+
} else if ("EXCLUDE_INLINED_ROOTS".equals(modeStr)) {
328+
setMode(Mode.STATEMENTS);
329+
}
330+
}
331+
332+
private void setMode(Mode m) {
333+
Collection<Engine> all = getAllEngineInstances();
334+
335+
for (Engine engine : all) {
336+
CPUSampler sampler = CPUSampler.find(engine);
337+
338+
if (sampler != null) {
339+
sampler.setMode(m);
340+
}
341+
}
342+
}
343+
344+
private static class TruffleStackTrace {
345+
private StackTraceElement[] stack;
346+
private byte[] flags;
347+
348+
private TruffleStackTrace(StackTraceElement[] stack, byte[] flags) {
349+
this.stack = stack;
350+
this.flags = flags;
351+
}
352+
}
300353
}

visualvm/sampler.truffle/libsrc/org/graalvm/visualvm/sampler/truffle/stagent/TruffleMBean.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
public interface TruffleMBean {
3535
public Map<String, Object>[] dumpAllThreads();
3636
public boolean isStackTracesEnabled();
37+
public void setTrackFlags(boolean trackFlags);
38+
public void setMode(String mode);
3739
public Map<String, Object>[] heapHistogram();
3840
public boolean isHeapHistogramEnabled();
3941
}

visualvm/sampler.truffle/src/org/graalvm/visualvm/sampler/truffle/SamplerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ public void run() {
508508
private void initializeCpuSampling() {
509509
VisualVM.getInstance().runTask(new Runnable() {
510510
public void run() {
511-
ThreadInfoProvider ti = new ThreadInfoProvider(application);
511+
ThreadInfoProvider ti = new ThreadInfoProvider(application, "ROOTS", true);
512512
final String status = ti.getStatus();
513513

514514
if (status != null) {

visualvm/sampler.truffle/src/org/graalvm/visualvm/sampler/truffle/cpu/CPUSamplerSupport.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,21 +249,45 @@ public void run() {
249249
}
250250
}
251251

252+
private static final int COMPILED = 1; // 0001
253+
private static final int INLINED = 2; // 0010
254+
252255
private void addSourceNames(Map<String,Object>[] infoMap) {
253256
for (Map<String,Object> threadInfo : infoMap) {
254257
StackTraceElement[] stack = (StackTraceElement[]) threadInfo.get("stack"); // NOI18N
258+
byte[] flags = (byte[]) threadInfo.get("flags"); // NOI18N
255259

256260
for (int i = 0; i <stack.length; i++) {
257261
StackTraceElement ste = stack[i];
262+
byte flag = flags[i];
258263
File file = new File(ste.getFileName());
259264
String fname = file.getName();
260-
String detailedName = ste.getMethodName()+"|(L"+fname+":"+ste.getLineNumber()+";)L;"; // NOI18N
265+
String flagSrt = "";
266+
if (isCompiled(flag)) {
267+
flagSrt = "compiled";
268+
if (isInlined(flag)) {
269+
flagSrt += ", ";
270+
flagSrt += "inlined";
271+
}
272+
flagSrt=" ["+flagSrt+"]";
273+
} else {
274+
assert !isInlined(flag);
275+
}
276+
String detailedName = ste.getMethodName()+flagSrt+"|(L"+fname+":"+ste.getLineNumber()+";)L;"; // NOI18N
261277
stack[i] = new StackTraceElement(ste.getClassName(), detailedName, ste.getFileName(), ste.getLineNumber());
262278
}
263279
}
264280
}
281+
282+
private boolean isCompiled(byte flag) {
283+
return (flag&COMPILED)==COMPILED;
284+
}
285+
286+
private boolean isInlined(byte flag) {
287+
return (flag&INLINED)==INLINED;
288+
}
265289
}
266-
290+
267291
public static abstract class ThreadDumper {
268292
public abstract void takeThreadDump(boolean openView);
269293
}

visualvm/sampler.truffle/src/org/graalvm/visualvm/sampler/truffle/cpu/ThreadInfoProvider.java

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@
3737
import java.util.Map;
3838
import java.util.logging.Level;
3939
import java.util.logging.Logger;
40+
import javax.management.Attribute;
4041
import javax.management.AttributeNotFoundException;
4142
import javax.management.InstanceNotFoundException;
43+
import javax.management.InvalidAttributeValueException;
4244
import javax.management.MBeanException;
4345
import javax.management.MBeanServerConnection;
4446
import javax.management.MalformedObjectNameException;
@@ -58,18 +60,17 @@ public final class ThreadInfoProvider {
5860
private static String AGENT_PATH = "modules/ext/stagent.jar"; // NOI18N
5961

6062
final private String status;
61-
private ObjectName truffleObjectName;
62-
private MBeanServerConnection conn;
63+
private ProxyTruffleMBean tbean;
6364

64-
public ThreadInfoProvider(Application app) {
65-
status = initialize(app);
65+
public ThreadInfoProvider(Application app, String mode, boolean trackFlags) {
66+
status = initialize(app, mode, trackFlags);
6667
}
6768

6869
public String getStatus() {
6970
return status;
7071
}
7172

72-
private String initialize(Application application) {
73+
private String initialize(Application application, String mode, boolean trackFlags) {
7374
if (application.getState() != Stateful.STATE_AVAILABLE) {
7475
return NbBundle.getMessage(ThreadInfoProvider.class, "MSG_unavailable"); // NOI18N
7576
}
@@ -80,16 +81,18 @@ private String initialize(Application application) {
8081
if (jmxModel.getConnectionState() != JmxModel.ConnectionState.CONNECTED) {
8182
return NbBundle.getMessage(ThreadInfoProvider.class, "MSG_unavailable_create_jmx"); // NOI18N
8283
}
83-
conn = jmxModel.getMBeanServerConnection();
8484

8585
try {
86-
if (!checkandLoadJMX(application)) {
86+
tbean = new ProxyTruffleMBean(jmxModel.getMBeanServerConnection());
87+
if (!checkAndLoadJMX(application)) {
8788
return NbBundle.getMessage(ThreadInfoProvider.class, "MSG_unavailable_threads");
8889
}
89-
if (!isStackTracesEnabled()) {
90+
if (!tbean.isStackTracesEnabled()) {
9091
return NbBundle.getMessage(ThreadInfoProvider.class, "MSG_unavailable_stacktraces");
9192
}
92-
dumpAllThreads();
93+
tbean.setTrackFlags(trackFlags);
94+
tbean.setMode(mode);
95+
tbean.dumpAllThreads();
9396
} catch (SecurityException e) {
9497
LOGGER.log(Level.INFO, "threadBean.getThreadInfo(ids, maxDepth) throws SecurityException for " + application, e); // NOI18N
9598
return NbBundle.getMessage(ThreadInfoProvider.class, "MSG_unavailable_threads"); // NOI18N
@@ -101,28 +104,23 @@ private String initialize(Application application) {
101104
}
102105

103106
Map<String, Object>[] dumpAllThreads() throws InstanceNotFoundException, MBeanException, ReflectionException, IOException {
104-
return (Map[]) conn.invoke(truffleObjectName, "dumpAllThreads", null, null);
107+
return tbean.dumpAllThreads();
105108
}
106109

107-
boolean isStackTracesEnabled() throws InstanceNotFoundException, MBeanException, IOException, ReflectionException, AttributeNotFoundException {
108-
return (boolean) conn.getAttribute(truffleObjectName, "StackTracesEnabled");
109-
}
110-
111-
boolean checkandLoadJMX(Application app) throws MalformedObjectNameException, IOException, InterruptedException {
110+
boolean checkAndLoadJMX(Application app) throws MalformedObjectNameException, IOException, InterruptedException {
112111
synchronized (app) {
113-
truffleObjectName = new ObjectName("com.truffle:type=Threading");
114-
if (conn.isRegistered(truffleObjectName)) {
112+
if (tbean.isRegistered()) {
115113
return true;
116114
}
117115
if (loadAgent(app)) {
118116
for (int i = 0; i < 10; i++) {
119-
if (conn.isRegistered(truffleObjectName)) {
117+
if (tbean.isRegistered()) {
120118
return true;
121119
}
122120
Thread.sleep(300);
123121
}
124122
}
125-
return conn.isRegistered(truffleObjectName);
123+
return tbean.isRegistered();
126124
}
127125
}
128126

@@ -175,4 +173,36 @@ private String getAgentPath() {
175173

176174
return jar.getAbsolutePath();
177175
}
176+
177+
private class ProxyTruffleMBean {
178+
private static final String TRUFFLE_OBJECT_NAME = "com.truffle:type=Threading";
179+
180+
private final ObjectName truffleObjectName;
181+
private final MBeanServerConnection conn;
182+
183+
ProxyTruffleMBean(MBeanServerConnection c) throws MalformedObjectNameException {
184+
conn = c;
185+
truffleObjectName = new ObjectName(TRUFFLE_OBJECT_NAME);
186+
}
187+
188+
Map<String, Object>[] dumpAllThreads() throws InstanceNotFoundException, MBeanException, ReflectionException, IOException {
189+
return (Map[]) conn.invoke(truffleObjectName, "dumpAllThreads", null, null);
190+
}
191+
192+
boolean isStackTracesEnabled() throws InstanceNotFoundException, MBeanException, IOException, ReflectionException, AttributeNotFoundException {
193+
return (boolean) conn.getAttribute(truffleObjectName, "StackTracesEnabled");
194+
}
195+
196+
void setTrackFlags(boolean trackFlags) throws InstanceNotFoundException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException, IOException {
197+
conn.setAttribute(truffleObjectName, new Attribute("TrackFlags", trackFlags));
198+
}
199+
200+
void setMode(String mode) throws InstanceNotFoundException, MBeanException, ReflectionException, IOException, AttributeNotFoundException, InvalidAttributeValueException {
201+
conn.setAttribute(truffleObjectName, new Attribute("Mode", mode));
202+
}
203+
204+
boolean isRegistered() throws IOException {
205+
return conn.isRegistered(truffleObjectName);
206+
}
207+
}
178208
}

0 commit comments

Comments
 (0)