package org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph;
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Deque;
import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.tracecompass.common.core.NonNullUtils;
+
import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.AggregatedCalledFunction;
import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.ThreadNode;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
-import com.google.common.collect.Lists;
-
/**
* Content provider for the flame graph view
*
*/
public class FlameGraphContentProvider implements ITimeGraphContentProvider {
- private List<FlamegraphDepthEntry> fFlameGraphEntries = new ArrayList<>();
- private long fThreadDuration;
+ private final List<FlamegraphDepthEntry> fFlameGraphEntries = new ArrayList<>();
private ITmfTrace fActiveTrace;
+ private SortOption fSortOption = SortOption.BY_NAME;
+ private @NonNull Comparator<FlamegraphDepthEntry> fThreadComparator = new ThreadNameComparator();
+
/**
* Parse the aggregated tree created by the callGraphAnalysis and creates
* A stack used to save the functions timeStamps
*/
private void setData(AggregatedCalledFunction firstNode, List<FlamegraphDepthEntry> childrenEntries, Deque<Long> timestampStack) {
+ long lastEnd = timestampStack.peek();
for (int i = 0; i < firstNode.getMaxDepth(); i++) {
if (i >= childrenEntries.size()) {
- FlamegraphDepthEntry entry = new FlamegraphDepthEntry(String.valueOf(i), 0, fActiveTrace.getEndTime().toNanos() - fActiveTrace.getStartTime().toNanos(), i, i);
+ FlamegraphDepthEntry entry = new FlamegraphDepthEntry(String.valueOf(i), 0, firstNode.getDuration(), i, i);
childrenEntries.add(entry);
}
+ childrenEntries.get(i).updateEndTime(lastEnd + firstNode.getDuration());
}
- FlamegraphDepthEntry firstEntry = NonNullUtils.checkNotNull(childrenEntries.get(0));
- firstEntry.addEvent(new FlamegraphEvent(firstEntry, timestampStack.peek(), firstNode));
+ FlamegraphDepthEntry firstEntry = checkNotNull(childrenEntries.get(0));
+ firstEntry.addEvent(new FlamegraphEvent(firstEntry, lastEnd, firstNode));
// Build the event list for next entries (next depth)
addEvent(firstNode, childrenEntries, timestampStack);
+ timestampStack.pop();
}
/**
timestampStack.pop();
});
}
- FlamegraphDepthEntry entry = NonNullUtils.checkNotNull(childrenEntries.get(node.getDepth()));
+ FlamegraphDepthEntry entry = checkNotNull(childrenEntries.get(node.getDepth()));
// Create the event corresponding to the function using the caller's
// timestamp
entry.addEvent(new FlamegraphEvent(entry, timestampStack.peek(), node));
}
}
}
- // Reverse the order of threads
- fFlameGraphEntries = Lists.reverse(fFlameGraphEntries);
+ // Sort the threads
+ fFlameGraphEntries.sort(fThreadComparator);
return fFlameGraphEntries.toArray(new ITimeGraphEntry[fFlameGraphEntries.size()]);
}
* The node of the aggregation tree
*/
private void buildChildrenEntries(ThreadNode threadNode) {
- FlamegraphDepthEntry threadEntry = new FlamegraphDepthEntry("", 0, fActiveTrace.getEndTime().toNanos() - fActiveTrace.getStartTime().toNanos(), fFlameGraphEntries.size(), threadNode.getId()); //$NON-NLS-1$
+ FlamegraphDepthEntry threadEntry = new FlamegraphDepthEntry("", 0, 0, fFlameGraphEntries.size(), threadNode.getId()); //$NON-NLS-1$
List<FlamegraphDepthEntry> childrenEntries = new ArrayList<>();
- fThreadDuration = 0L;
+ Deque<Long> timestampStack = new ArrayDeque<>();
+ timestampStack.push(0L);
// Sort children by duration
threadNode.getChildren().stream()
.sorted(Comparator.comparingLong(AggregatedCalledFunction::getDuration))
.forEach(rootFunction -> {
- Deque<Long> timestampStack = new ArrayDeque<>();
- timestampStack.push(fThreadDuration);
setData(rootFunction, childrenEntries, timestampStack);
- fThreadDuration += rootFunction.getDuration();
- timestampStack.pop();
+ long currentThreadDuration = timestampStack.pop() + rootFunction.getDuration();
+ timestampStack.push(currentThreadDuration);
});
childrenEntries.forEach(child -> {
if (child != null) {
threadEntry.addChild(child);
}
});
+ threadEntry.updateEndTime(timestampStack.pop());
threadEntry.setName(threadNode.getSymbol().toString());
fFlameGraphEntries.add(threadEntry);
}
// Do nothing
}
+
+ /**
+ * Get the sort option
+ *
+ * @return the sort option.
+ */
+ public SortOption getSortOption() {
+ return fSortOption;
+ }
+
+ /**
+ * Set the sort option for sorting the thread entries
+ *
+ * @param sortOption
+ * the sort option to set
+ *
+ */
+ public void setSortOption(SortOption sortOption) {
+ fSortOption = sortOption;
+ switch (sortOption) {
+ case BY_NAME:
+ fThreadComparator = new ThreadNameComparator();
+ break;
+ case BY_NAME_REV:
+ fThreadComparator = checkNotNull(new ThreadNameComparator().reversed());
+ break;
+ case BY_ID:
+ fThreadComparator = new ThreadIdComparator();
+ break;
+ case BY_ID_REV:
+ fThreadComparator = checkNotNull(new ThreadIdComparator().reversed());
+ break;
+ default:
+ break;
+ }
+ }
}