lttng: Update LTTng event matching to use event layout
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.timing.ui / src / org / eclipse / tracecompass / internal / analysis / timing / ui / flamegraph / FlameGraphContentProvider.java
CommitLineData
74ccf789
SF
1/*******************************************************************************
2 * Copyright (c) 2016 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9
10package org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph;
11
12import java.util.ArrayDeque;
13import java.util.ArrayList;
14import java.util.Comparator;
15import java.util.Deque;
16import java.util.List;
17
18import org.eclipse.jface.viewers.Viewer;
19import org.eclipse.tracecompass.common.core.NonNullUtils;
20import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.AggregatedCalledFunction;
21import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
22import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
23import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphContentProvider;
24import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
25import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
26
27import com.google.common.collect.Lists;
28
29/**
30 * Content provider for the flame graph view
31 *
32 * @author Sonia Farrah
33 *
34 */
35public class FlameGraphContentProvider implements ITimeGraphContentProvider {
36
37 private static final int MODULO = FlameGraphPresentationProvider.NUM_COLORS / 2;
38 private List<FlamegraphDepthEntry> fFlameGraphEntries = new ArrayList<>();
39 private long fThreadDuration;
40 private ITmfTrace fActiveTrace;
41
42 /**
43 * Parse the aggregated tree created by the callGraphAnalysis and creates
44 * the event list (functions) for each entry (depth)
45 *
46 * @param firstNode
47 * The first node of the aggregation tree
48 * @param childrenEntries
49 * The list of entries for one thread
50 * @param timestampStack
51 * A stack used to save the functions timeStamps
52 */
53 private void setData(AggregatedCalledFunction firstNode, List<FlamegraphDepthEntry> childrenEntries, Deque<Long> timestampStack) {
54 for (int i = 0; i < firstNode.getMaxDepth(); i++) {
55 if (i >= childrenEntries.size()) {
56 FlamegraphDepthEntry entry = new FlamegraphDepthEntry(String.valueOf(i), 0, fActiveTrace.getEndTime().toNanos() - fActiveTrace.getStartTime().toNanos(), i);
57 childrenEntries.add(entry);
58 }
59 }
60 int value = String.valueOf(firstNode.getSymbol()).hashCode() % MODULO + MODULO;
61 FlamegraphDepthEntry firstEntry = NonNullUtils.checkNotNull(childrenEntries.get(0));
62 firstEntry.addEvent(new FlamegraphEvent(firstEntry, timestampStack.peek(), firstNode.getDuration(), value, firstNode.getSymbol(), 1, firstNode.getSelfTime()));
63 // Build the event list for next entries (next depth)
64 addEvent(firstNode, childrenEntries, timestampStack);
65 }
66
67 /**
68 * Build the events list for an entry (depth), then creates recursively the
69 * events for the next entries. This parses the aggregation tree starting
70 * from the bottom. This uses a stack to save the timestamp for each
71 * function. Once we save a function's timestamp we'll use it to create the
72 * callees events.
73 *
74 * @param node
75 * The node of the aggregation tree
76 * @param childrenEntries
77 * The list of entries for one thread
78 * @param timestampStack
79 * A stack used to save the functions timeStamps
80 */
81 private void addEvent(AggregatedCalledFunction node, List<FlamegraphDepthEntry> childrenEntries, Deque<Long> timestampStack) {
82 if (node.hasChildren()) {
83 node.getChildren().stream()
84 .sorted(Comparator.comparingLong(AggregatedCalledFunction::getDuration))
85 .forEach(child -> {
86 addEvent(child, childrenEntries, timestampStack);
87 });
88 // Pop the children timestamps from the stack
89 node.getChildren().stream().forEach(child -> {
90 timestampStack.pop();
91 });
92 }
93 FlamegraphDepthEntry entry = NonNullUtils.checkNotNull(childrenEntries.get(node.getDepth()));
94 // Get the color of the event
95 int value = String.valueOf(node.getSymbol()).hashCode() % MODULO + MODULO;
96 // Create the event corresponding to the function using the caller's
97 // timestamp
98 entry.addEvent(new FlamegraphEvent(entry, timestampStack.peek(),
99 node.getDuration(), value, node.getSymbol(), node.getNbCalls(),
100 node.getSelfTime()));
101 timestampStack.push(timestampStack.peek() + node.getDuration());
102 }
103
104 @Override
105 public boolean hasChildren(Object element) {
106 return !fFlameGraphEntries.isEmpty();
107 }
108
109 @Override
110 public ITimeGraphEntry[] getElements(Object inputElement) {
111 fFlameGraphEntries.clear();
112 // Get the root of each thread
113 fActiveTrace = TmfTraceManager.getInstance().getActiveTrace();
114 if (fActiveTrace == null) {
115 return new ITimeGraphEntry[0];
116 }
117
118 if (inputElement instanceof List<?>) {
119 List<?> threadNodes = (List<?>) inputElement;
120 for (Object object : threadNodes) {
121 if (object instanceof AggregatedCalledFunction) {
122 buildChildrenEntries((AggregatedCalledFunction) object);
123 }
124 }
125 }
126 // Reverse the order of threads
127 fFlameGraphEntries = Lists.reverse(fFlameGraphEntries);
128 return fFlameGraphEntries.toArray(new ITimeGraphEntry[fFlameGraphEntries.size()]);
129 }
130
131 /**
132 * Build the entry list for one thread
133 *
134 * @param threadNode
135 * The node of the aggregation tree
136 */
137 private void buildChildrenEntries(AggregatedCalledFunction threadNode) {
138 FlamegraphDepthEntry threadEntry = new FlamegraphDepthEntry("", 0, fActiveTrace.getEndTime().toNanos() - fActiveTrace.getStartTime().toNanos(), fFlameGraphEntries.size()); //$NON-NLS-1$
139 List<FlamegraphDepthEntry> childrenEntries = new ArrayList<>();
140 fThreadDuration = 0L;
141 // Sort children by duration
142 threadNode.getChildren().stream()
143 .sorted(Comparator.comparingLong(AggregatedCalledFunction::getDuration))
144 .forEach(rootFunction -> {
145 Deque<Long> timestampStack = new ArrayDeque<>();
146 timestampStack.push(fThreadDuration);
147 setData(rootFunction, childrenEntries, timestampStack);
148 fThreadDuration += rootFunction.getDuration();
149 timestampStack.pop();
150 });
151 childrenEntries.forEach(child -> {
152 if (child != null) {
153 threadEntry.addChild(child);
154 }
155 });
156 threadEntry.setName(threadNode.getSymbol().toString());
157 fFlameGraphEntries.add(threadEntry);
158 }
159
160 @Override
161 public ITimeGraphEntry[] getChildren(Object parentElement) {
162 return fFlameGraphEntries.toArray(new TimeGraphEntry[fFlameGraphEntries.size()]);
163 }
164
165 @Override
166 public ITimeGraphEntry getParent(Object element) {
167 // Do nothing
168 return null;
169 }
170
171 @Override
172 public void dispose() {
173 // Do nothing
174 }
175
176 @Override
177 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
178 // Do nothing
179 }
180
181}
This page took 0.031648 seconds and 5 git commands to generate.