timing: Add Flame Graph View
authorSonia Farrah <sonia.farrah@ericsson.com>
Tue, 5 Jul 2016 18:39:55 +0000 (14:39 -0400)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Wed, 10 Aug 2016 13:52:39 +0000 (09:52 -0400)
The Call Graph analysis creates an aggregation tree for the call stack
view. The functions in the tree are aggregated by address and caller.

The tree nodes have links to their children and parents.

This tree is used to fill a flame graph view.

The Flame Graph is used to analyze the function call durations in a more
aggregated manner. This will show users which function call is consuming
the most time and what call chain is consuming the most time.

Change-Id: I4da99847ecef1e5246be27a2719957a568c8cae6
Signed-off-by: Sonia Farrah <sonia.farrah@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/76636
Reviewed-by: Genevieve Bastien <gbastien+lttng@versatic.net>
Tested-by: Genevieve Bastien <gbastien+lttng@versatic.net>
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
17 files changed:
analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/AggregatedCalledFunction.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/CallGraphAnalysis.java
analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/Messages.java
analysis/org.eclipse.tracecompass.analysis.timing.ui/META-INF/MANIFEST.MF
analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/elcl16/flame.png [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/plugin.properties
analysis/org.eclipse.tracecompass.analysis.timing.ui/plugin.xml
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphContentProvider.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphPresentationProvider.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphView.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlamegraphDepthEntry.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlamegraphEvent.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/Messages.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/messages.properties [new file with mode: 0644]
lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/callstack/LttngUstCallStackAnalysisRequirement.java
lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/callstack/Messages.java
lttng/org.eclipse.tracecompass.lttng2.ust.ui/src/org/eclipse/tracecompass/internal/lttng2/ust/ui/analysis/callstack/messages.properties

diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/AggregatedCalledFunction.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/internal/analysis/timing/core/callgraph/AggregatedCalledFunction.java
new file mode 100644 (file)
index 0000000..307bc8a
--- /dev/null
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.timing.core.callgraph;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+
+/**
+ * This class represents a function call in a certain level in the call
+ * stack. It's used to build an aggregation segment tree (aggregated by depth and
+ * callers). Per example,the two calls to the function A() in the call graph
+ * below will be combined into one node in the generated tree:
+ *
+ * <pre>
+ *   (Depth=0)      main              main
+ *               ↓↑  ↓↑   ↓↑    =>   ↓↑   ↓↑
+ *   (Depth=1)  A()  B()  A()       A()   B()
+ * </pre>
+ *
+ * @author Sonia Farrah
+ *
+ */
+public class AggregatedCalledFunction {
+
+    // ------------------------------------------------------------------------
+    // Attributes
+    // ------------------------------------------------------------------------
+
+    private final Object fSymbol;
+    private final int fDepth;
+    private final int fMaxDepth;
+    private final Map<Object, AggregatedCalledFunction> fChildren = new HashMap<>();
+    private final @Nullable AggregatedCalledFunction fParent;
+    private int fNbCalls = 0;
+    private long fDuration;
+    private long fSelfTime;
+
+    /**
+     * Constructor
+     * @param symbol
+     *         The function's name or address
+     * @param duration
+     *          The function's duration
+     * @param depth
+     *          The function's depth
+     * @param maxDepth
+     *          The aggregation tree's maximum depth
+     * @param parent
+     *          The function's caller
+     */
+    public AggregatedCalledFunction(Object symbol, long duration, int depth, int maxDepth, @Nullable AggregatedCalledFunction parent) {
+        fSymbol = symbol;
+        fDuration = duration;
+        fSelfTime = duration;
+        fDepth = depth;
+        fMaxDepth = maxDepth;
+        fParent = parent;
+    }
+
+    /**
+     * The function's symbol (address or name)
+     *
+     * @return The function's symbol
+     */
+    public Object getSymbol() {
+        return fSymbol;
+    }
+
+    /**
+     * The callees of the function
+     *
+     * @return The function's callees
+     */
+    public synchronized Collection<AggregatedCalledFunction> getChildren() {
+        return fChildren.values();
+    }
+
+    /**
+     * The function's caller
+     *
+     * @return The caller of a function
+     */
+    public @Nullable AggregatedCalledFunction getParent() {
+        return fParent;
+    }
+
+    /**
+     * Add a new callee into the Callees list. If the function exists in the
+     * callees list, the new callee's duration will be added to its duration and
+     * it'll combine their callees.
+     *
+     * @param child
+     *            The callees of a function
+     */
+    public synchronized void addChild(AggregatedCalledFunction child) {
+        AggregatedCalledFunction node = fChildren.get(child.getSymbol());
+        if (node == null) {
+            child.incrementCalls();
+            fChildren.put(child.getSymbol(), child);
+        } else {
+            merge(node, child);
+            fChildren.replace(node.getSymbol(), node);
+        }
+        fSelfTime -= child.fDuration;
+    }
+
+    /**
+     * Modify the function's duration
+     *
+     * @param duration
+     *            The amount to increment the duration by
+     */
+    private void addToDuration(long duration) {
+        fDuration += duration;
+    }
+
+    /**
+     * Merge the callees of two functions.
+     *
+     * @param firstNode
+     *            The first parent secondNode The second parent
+     */
+    private static void mergeChildren(AggregatedCalledFunction firstNode, AggregatedCalledFunction secondNode) {
+        for (Map.Entry<Object, AggregatedCalledFunction> FunctionEntry : secondNode.fChildren.entrySet()) {
+            Object childSymbol = NonNullUtils.checkNotNull(FunctionEntry.getKey());
+            AggregatedCalledFunction secondNodeChild = NonNullUtils.checkNotNull(FunctionEntry.getValue());
+            AggregatedCalledFunction aggregatedCalledFunction = firstNode.fChildren.get(childSymbol);
+            if (aggregatedCalledFunction == null) {
+                firstNode.fChildren.put(secondNodeChild.getSymbol(), secondNodeChild);
+            } else {
+                // combine children
+                AggregatedCalledFunction firstNodeChild = aggregatedCalledFunction;
+                merge(firstNodeChild, secondNodeChild);
+                firstNode.fChildren.replace(firstNodeChild.getSymbol(), firstNodeChild);
+            }
+        }
+    }
+
+    /**
+     * Merge two functions, add durations, self times, increment the calls,
+     * update statistics and merge children.
+     *
+     * @param destination
+     *            the node to merge to
+     * @param source
+     *            the node to merge
+     */
+    private static void merge(AggregatedCalledFunction destination, AggregatedCalledFunction source) {
+        destination.addToDuration(source.getDuration());
+        destination.addToSelfTime(source.getSelfTime());
+        destination.incrementCalls();
+        // merge the children callees.
+        mergeChildren(destination, source);
+    }
+
+    /**
+     * The function's duration
+     *
+     * @return The duration of the function
+     */
+    public long getDuration() {
+        return fDuration;
+    }
+
+    /**
+     * The function's depth
+     *
+     * @return The depth of the function
+     */
+    public int getDepth() {
+        return fDepth;
+    }
+
+    /**
+     * The depth of the aggregated tree
+     *
+     * @return The depth of the aggregated tree
+     */
+    public int getMaxDepth() {
+        return fMaxDepth;
+    }
+
+    /**
+     * The number of calls of a function
+     *
+     * @return The number of calls of a function
+     */
+    public int getNbCalls() {
+        return fNbCalls;
+    }
+
+    /**
+     * The number of calls of a function
+     */
+    public void incrementCalls() {
+        fNbCalls++;
+    }
+
+    /**
+     * The self time of an aggregated function
+     *
+     * @return The self time
+     */
+    public long getSelfTime() {
+        return fSelfTime;
+    }
+
+    /**
+     * Add to the self time of an aggregated function
+     *
+     * @param selfTime
+     *            The amount of self time to add
+     */
+    public void addToSelfTime(long selfTime) {
+        fSelfTime += selfTime;
+    }
+
+    /**
+     * Returns whether the function has callees.
+     *
+     * @return Boolean
+     */
+    public Boolean hasChildren() {
+        return !fChildren.isEmpty();
+    }
+}
index c9b5854c342a34775a3b47bc0469dbbc026dd59e..b75e11eba6c9c50d8e498b5a8af925e08c5bb7ca 100644 (file)
@@ -85,6 +85,11 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem
      * The sub attributes of a certain thread
      */
     private List<Integer> fCurrentQuarks = Collections.emptyList();
+    /**
+     * The List of thread nodes. Each thread has a virtual node having the root
+     * function as children
+     */
+    private List<AggregatedCalledFunction> fThreadNodes = new ArrayList<>();
 
     /**
      * Default constructor
@@ -199,6 +204,8 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem
      * @return Boolean
      */
     private boolean iterateOverQuark(ITmfStateSystem stateSystem, int quark, String[] subAttributePath, IProgressMonitor monitor) {
+        String threadName = stateSystem.getAttributeName(quark);
+        AggregatedCalledFunction init = new AggregatedCalledFunction(threadName, 0L, 0, 0, null);
         try {
             long curTime = stateSystem.getStartTime();
             long limit = stateSystem.getCurrentEndTime();
@@ -222,10 +229,11 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem
                     // Create the segment for the first call event.
                     AbstractCalledFunction segment = CalledFunctionFactory.create(intervalStart, intervalEnd + 1, depth, stateValue, null);
                     fRootFunctions.add(segment);
-                    if (!findChildren(segment, depth, stateSystem, fCurrentQuarks.size() + fCurrentQuarks.get(depth), monitor)) {
+                    AggregatedCalledFunction firstNode = new AggregatedCalledFunction(stateValue, intervalEnd - intervalStart + 1, segment.getDepth(), fCurrentQuarks.size(), null);
+                    if (!findChildren(segment, depth, stateSystem, fCurrentQuarks.size() + fCurrentQuarks.get(depth), firstNode, monitor)) {
                         return false;
                     }
-
+                    init.addChild(firstNode);
                 }
 
                 curTime = interval.getEndTime() + 1;
@@ -235,6 +243,7 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem
             Activator.getInstance().logError(Messages.QueringStateSystemError, e);
             return false;
         }
+        fThreadNodes.add(init);
         return true;
     }
 
@@ -251,11 +260,13 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem
      *            The quark of the segment parent ss The actual state system
      * @param maxQuark
      *            The last quark in the state system
+     * @param AggregatedCalledFunction
+     *            A node in the aggregation tree
      * @param monitor
      *            The progress monitor The progress monitor TODO: if stack size
      *            is an issue, convert to a stack instead of recursive function
      */
-    private boolean findChildren(AbstractCalledFunction node, int depth, ITmfStateSystem ss, int maxQuark, IProgressMonitor monitor) {
+    private boolean findChildren(AbstractCalledFunction node, int depth, ITmfStateSystem ss, int maxQuark, AggregatedCalledFunction aggregatedCalledFunction, IProgressMonitor monitor) {
         fStore.add(node);
         long curTime = node.getStart();
         long limit = node.getEnd();
@@ -282,8 +293,10 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem
                     return true;
                 }
                 AbstractCalledFunction segment = CalledFunctionFactory.create(intervalStart, intervalEnd + 1, node.getDepth() + 1, stateValue, node);
+                AggregatedCalledFunction childNode = new AggregatedCalledFunction(stateValue, segment.getLength(), segment.getDepth(), aggregatedCalledFunction.getMaxDepth(), aggregatedCalledFunction);
                 // Search for the children with the next quark.
-                findChildren(segment, depth + 1, ss, maxQuark, monitor);
+                findChildren(segment, depth + 1, ss, maxQuark, childNode, monitor);
+                aggregatedCalledFunction.addChild(childNode);
                 node.addChild(segment);
             }
             curTime = interval.getEndTime() + 1;
@@ -342,4 +355,14 @@ public abstract class CallGraphAnalysis extends TmfAbstractAnalysisModule implem
         return ImmutableList.copyOf(fRootFunctions);
     }
 
+    /**
+     * List of thread nodes. Each thread has a virtual node having the root
+     * functions called as children.
+     *
+     * @return The thread nodes
+     */
+    public List<AggregatedCalledFunction> getThreadNodes() {
+        return ImmutableList.copyOf(fThreadNodes);
+    }
+
 }
\ No newline at end of file
index 1a5cd49f912919daff679c30fce8efcbe1a3fe5e..12f540d2abe52229b4005c670e4b6fff568e87dc 100644 (file)
@@ -17,7 +17,7 @@ import org.eclipse.osgi.util.NLS;
  * @author Sonia Farrah
  */
 public class Messages extends NLS {
-    private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.messages"; //$NON-NLS-1$
+    private static final String BUNDLE_NAME = Messages.class.getPackage().getName() + ".messages"; //$NON-NLS-1$
     /**
      * Analysis description for the help
      */
index 7927e757f78158d0a27f2922e3e491f7c442d5b9..2f943c494d1563af0115b3551f27bec360f09651 100644 (file)
@@ -26,6 +26,7 @@ Export-Package: org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore,
  org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table,
  org.eclipse.tracecompass.internal.analysis.timing.ui,
  org.eclipse.tracecompass.internal.analysis.timing.ui.callgraph;x-internal:=true,
+ org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph;x-internal:=true,
  org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.density,
  org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter,
  org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.statistics,
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/elcl16/flame.png b/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/elcl16/flame.png
new file mode 100644 (file)
index 0000000..baba97e
Binary files /dev/null and b/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/elcl16/flame.png differ
index 1f9d7a4ea5d287c9ae99e4c106fc0c7c1a1f6b4f..149a20ff5a26a7572f206d17f17159614f94bae5 100644 (file)
@@ -13,5 +13,6 @@ Bundle-Name = Trace Compass Graph Analysis UI Plug-in
 view.criticalpath = Critical Flow View
 view.execgraph = Execution Graph View
 view.callgraphDensity= Function Durations Distribution
+view.flameGraph= Flame Graph
 
 callgraph.analysis = Call Graph Analysis
\ No newline at end of file
index a367e8737f5898b18a587f8483474421e6997c39..ecb2836713c7461d5cc89751549aeb624666db98 100644 (file)
                class="org.eclipse.tracecompass.internal.analysis.timing.ui.callgraph.CallGraphAnalysisUI">
          </analysisModuleClass>
       </output>
+      <output
+            class="org.eclipse.tracecompass.tmf.ui.analysis.TmfAnalysisViewOutput"
+            id="org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph.flamegraphView">
+         <analysisModuleClass
+               class="org.eclipse.tracecompass.internal.analysis.timing.ui.callgraph.CallGraphAnalysisUI">
+         </analysisModuleClass>
+      </output>
    </extension>
    <extension
          point="org.eclipse.ui.views">
             name="%view.callgraphDensity"
             restorable="true">
       </view>
+      <view
+            category="org.eclipse.linuxtools.tmf.ui.views.category"
+            class="org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph.FlameGraphView"
+            icon="icons/elcl16/flame.png"
+            id="org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph.flamegraphView"
+            name="%view.flameGraph"
+            restorable="true">
+      </view>
    </extension>
 </plugin>
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphContentProvider.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphContentProvider.java
new file mode 100644 (file)
index 0000000..2b960f1
--- /dev/null
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.List;
+
+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.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphContentProvider;
+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
+ *
+ * @author Sonia Farrah
+ *
+ */
+public class FlameGraphContentProvider implements ITimeGraphContentProvider {
+
+    private static final int MODULO = FlameGraphPresentationProvider.NUM_COLORS / 2;
+    private List<FlamegraphDepthEntry> fFlameGraphEntries = new ArrayList<>();
+    private long fThreadDuration;
+    private ITmfTrace fActiveTrace;
+
+    /**
+     * Parse the aggregated tree created by the callGraphAnalysis and creates
+     * the event list (functions) for each entry (depth)
+     *
+     * @param firstNode
+     *            The first node of the aggregation tree
+     * @param childrenEntries
+     *            The list of entries for one thread
+     * @param timestampStack
+     *            A stack used to save the functions timeStamps
+     */
+    private void setData(AggregatedCalledFunction firstNode, List<FlamegraphDepthEntry> childrenEntries, Deque<Long> timestampStack) {
+        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);
+                childrenEntries.add(entry);
+            }
+        }
+        int value = String.valueOf(firstNode.getSymbol()).hashCode() % MODULO + MODULO;
+        FlamegraphDepthEntry firstEntry = NonNullUtils.checkNotNull(childrenEntries.get(0));
+        firstEntry.addEvent(new FlamegraphEvent(firstEntry, timestampStack.peek(), firstNode.getDuration(), value, firstNode.getSymbol(), 1, firstNode.getSelfTime()));
+        // Build the event list for next entries (next depth)
+        addEvent(firstNode, childrenEntries, timestampStack);
+    }
+
+    /**
+     * Build the events list for an entry (depth), then creates recursively the
+     * events for the next entries. This parses the aggregation tree starting
+     * from the bottom. This uses a stack to save the timestamp for each
+     * function. Once we save a function's timestamp we'll use it to create the
+     * callees events.
+     *
+     * @param node
+     *            The node of the aggregation tree
+     * @param childrenEntries
+     *            The list of entries for one thread
+     * @param timestampStack
+     *            A stack used to save the functions timeStamps
+     */
+    private void addEvent(AggregatedCalledFunction node, List<FlamegraphDepthEntry> childrenEntries, Deque<Long> timestampStack) {
+        if (node.hasChildren()) {
+            node.getChildren().stream()
+                    .sorted(Comparator.comparingLong(AggregatedCalledFunction::getDuration))
+                    .forEach(child -> {
+                        addEvent(child, childrenEntries, timestampStack);
+                    });
+            // Pop the children timestamps from the stack
+            node.getChildren().stream().forEach(child -> {
+                timestampStack.pop();
+            });
+        }
+        FlamegraphDepthEntry entry = NonNullUtils.checkNotNull(childrenEntries.get(node.getDepth()));
+        // Get the color of the event
+        int value = String.valueOf(node.getSymbol()).hashCode() % MODULO + MODULO;
+        // Create the event corresponding to the function using the caller's
+        // timestamp
+        entry.addEvent(new FlamegraphEvent(entry, timestampStack.peek(),
+                node.getDuration(), value, node.getSymbol(), node.getNbCalls(),
+                node.getSelfTime()));
+        timestampStack.push(timestampStack.peek() + node.getDuration());
+    }
+
+    @Override
+    public boolean hasChildren(Object element) {
+        return !fFlameGraphEntries.isEmpty();
+    }
+
+    @Override
+    public ITimeGraphEntry[] getElements(Object inputElement) {
+        fFlameGraphEntries.clear();
+        // Get the root of each thread
+        fActiveTrace = TmfTraceManager.getInstance().getActiveTrace();
+        if (fActiveTrace == null) {
+            return new ITimeGraphEntry[0];
+        }
+
+        if (inputElement instanceof List<?>) {
+            List<?> threadNodes = (List<?>) inputElement;
+            for (Object object : threadNodes) {
+                if (object instanceof AggregatedCalledFunction) {
+                    buildChildrenEntries((AggregatedCalledFunction) object);
+                }
+            }
+        }
+        // Reverse the order of threads
+        fFlameGraphEntries = Lists.reverse(fFlameGraphEntries);
+        return fFlameGraphEntries.toArray(new ITimeGraphEntry[fFlameGraphEntries.size()]);
+    }
+
+    /**
+     * Build the entry list for one thread
+     *
+     * @param threadNode
+     *            The node of the aggregation tree
+     */
+    private void buildChildrenEntries(AggregatedCalledFunction threadNode) {
+        FlamegraphDepthEntry threadEntry = new FlamegraphDepthEntry("", 0, fActiveTrace.getEndTime().toNanos() - fActiveTrace.getStartTime().toNanos(), fFlameGraphEntries.size()); //$NON-NLS-1$
+        List<FlamegraphDepthEntry> childrenEntries = new ArrayList<>();
+        fThreadDuration = 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();
+                });
+        childrenEntries.forEach(child -> {
+            if (child != null) {
+                threadEntry.addChild(child);
+            }
+        });
+        threadEntry.setName(threadNode.getSymbol().toString());
+        fFlameGraphEntries.add(threadEntry);
+    }
+
+    @Override
+    public ITimeGraphEntry[] getChildren(Object parentElement) {
+        return fFlameGraphEntries.toArray(new TimeGraphEntry[fFlameGraphEntries.size()]);
+    }
+
+    @Override
+    public ITimeGraphEntry getParent(Object element) {
+        // Do nothing
+        return null;
+    }
+
+    @Override
+    public void dispose() {
+        // Do nothing
+    }
+
+    @Override
+    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+        // Do nothing
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphPresentationProvider.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphPresentationProvider.java
new file mode 100644 (file)
index 0000000..0387e5b
--- /dev/null
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph;
+
+import java.text.Format;
+import java.text.NumberFormat;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.SubSecondTimeWithUnitFormat;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProvider;
+import org.eclipse.tracecompass.tmf.ui.symbols.SymbolProviderManager;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.StateItem;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.NullTimeEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Presentation provider for the flame graph view, based on the generic TMF
+ * presentation provider.
+ *
+ * @author Sonia Farrah
+ */
+public class FlameGraphPresentationProvider extends TimeGraphPresentationProvider {
+
+    /** Number of colors used for flameGraph events */
+    public static final int NUM_COLORS = 360;
+
+    private static final Format FORMATTER = new SubSecondTimeWithUnitFormat();
+
+    private FlameGraphView fView;
+
+    private Integer fAverageCharWidth;
+
+    private enum State {
+        MULTIPLE(new RGB(100, 100, 100)), EXEC(new RGB(0, 200, 0));
+
+        private final RGB rgb;
+
+        private State(RGB rgb) {
+            this.rgb = rgb;
+        }
+    }
+
+    /**
+     * Constructor
+     *
+     */
+    public FlameGraphPresentationProvider() {
+    }
+
+    @Override
+    public StateItem[] getStateTable() {
+        final float saturation = 0.6f;
+        final float brightness = 0.6f;
+        StateItem[] stateTable = new StateItem[NUM_COLORS + 1];
+        stateTable[0] = new StateItem(State.MULTIPLE.rgb, State.MULTIPLE.toString());
+        for (int i = 0; i < NUM_COLORS; i++) {
+            RGB rgb = new RGB(i, saturation, brightness);
+            stateTable[i + 1] = new StateItem(rgb, State.EXEC.toString());
+        }
+        return stateTable;
+    }
+
+    @Override
+    public boolean displayTimesInTooltip() {
+        return false;
+    }
+
+    @Override
+    public String getStateTypeName() {
+        return Messages.FlameGraph_Depth;
+    }
+
+    @Override
+    public Map<String, String> getEventHoverToolTipInfo(ITimeEvent event, long hoverTime) {
+        return ImmutableMap.of(
+                NonNullUtils.checkNotNull(Messages.FlameGraph_Duration), String.format("%s", FORMATTER.format(event.getDuration())), //$NON-NLS-1$
+                NonNullUtils.checkNotNull(Messages.FlameGraph_SelfTime), String.format("%s", FORMATTER.format(((FlamegraphEvent) event).getSelfTime())), //$NON-NLS-1$
+                NonNullUtils.checkNotNull(Messages.FlameGraph_NbCalls), NonNullUtils.checkNotNull(NumberFormat.getIntegerInstance().format(((FlamegraphEvent) event).getNbCalls())) // $NON-NLS-1$
+        );
+    }
+
+    @Override
+    public int getStateTableIndex(ITimeEvent event) {
+        if (event instanceof FlamegraphEvent) {
+            FlamegraphEvent flameGraphEvent = (FlamegraphEvent) event;
+            return flameGraphEvent.getValue() + 1;
+        } else if (event instanceof NullTimeEvent) {
+            return INVISIBLE;
+        }
+        return State.MULTIPLE.ordinal();
+    }
+
+    /**
+     * Get the event's symbol. It could be an address or a name.
+     *
+     * @param fGEvent
+     *            An event
+     * @param symbolProvider
+     *            A symbol provider
+     */
+    private static String getFuntionSymbol(FlamegraphEvent event, ISymbolProvider symbolProvider) {
+        String funcSymbol = ""; //$NON-NLS-1$
+        if (event.getSymbol() instanceof TmfStateValue) {
+            ITmfStateValue symbol = (ITmfStateValue) event.getSymbol();
+            switch (symbol.getType()) {
+            case LONG:
+                Long longAddress = symbol.unboxLong();
+                funcSymbol = symbolProvider.getSymbolText(longAddress);
+                if (funcSymbol == null) {
+                    return "0x" + Long.toHexString(longAddress); //$NON-NLS-1$
+                }
+                return funcSymbol;
+            case STRING:
+                return symbol.unboxStr();
+            case INTEGER:
+                Integer intAddress = symbol.unboxInt();
+                funcSymbol = symbolProvider.getSymbolText(intAddress);
+                if (funcSymbol == null) {
+                    return "0x" + Integer.toHexString(intAddress); //$NON-NLS-1$
+                }
+                return funcSymbol;
+            case CUSTOM:
+            case DOUBLE:
+            case NULL:
+            default:
+                break;
+            }
+        }
+        return funcSymbol;
+    }
+
+    @Override
+    public void postDrawEvent(ITimeEvent event, Rectangle bounds, GC gc) {
+        if (fAverageCharWidth == null) {
+            fAverageCharWidth = gc.getFontMetrics().getAverageCharWidth();
+        }
+        if (bounds.width <= fAverageCharWidth) {
+            return;
+        }
+        if (!(event instanceof FlamegraphEvent)) {
+            return;
+        }
+        String funcSymbol = ""; //$NON-NLS-1$
+        ITmfTrace activeTrace = TmfTraceManager.getInstance().getActiveTrace();
+        if (activeTrace != null) {
+            FlamegraphEvent fgEvent = (FlamegraphEvent) event;
+            ISymbolProvider symbolProvider = SymbolProviderManager.getInstance().getSymbolProvider(activeTrace);
+            funcSymbol = getFuntionSymbol(fgEvent, symbolProvider);
+        }
+        gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE));
+        Utils.drawText(gc, funcSymbol, bounds.x, bounds.y, bounds.width, bounds.height, true, true);
+    }
+
+    /**
+     * The flame graph view
+     *
+     * @return The flame graph view
+     */
+    public FlameGraphView getView() {
+        return fView;
+    }
+
+    /**
+     * The flame graph view
+     *
+     * @param view
+     *            The flame graph view
+     */
+    public void setView(FlameGraphView view) {
+        fView = view;
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphView.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphView.java
new file mode 100644 (file)
index 0000000..239e2f3
--- /dev/null
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Author:
+ *     Sonia Farrah
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.CallGraphAnalysis;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.callgraph.CallGraphAnalysisUI;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
+import org.eclipse.tracecompass.tmf.ui.editors.ITmfTraceEditor;
+import org.eclipse.tracecompass.tmf.ui.views.TmfView;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphPresentationProvider;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * View to display the flame graph .This uses the flameGraphNode tree generated
+ * by CallGraphAnalysisUI.
+ *
+ * @author Sonia Farrah
+ */
+public class FlameGraphView extends TmfView {
+
+    /**
+     *
+     */
+    public static final String ID = FlameGraphView.class.getPackage().getName() + ".flamegraphView"; //$NON-NLS-1$
+
+    private TimeGraphViewer fTimeGraphViewer;
+
+    private FlameGraphContentProvider fTimeGraphContentProvider;
+
+    private TimeGraphPresentationProvider fPresentationProvider;
+
+    private ITmfTrace fTrace;
+
+    /**
+     * Constructor
+     */
+    public FlameGraphView() {
+        super(ID);
+    }
+
+    @Override
+    public void createPartControl(Composite parent) {
+        super.createPartControl(parent);
+        fTimeGraphViewer = new TimeGraphViewer(parent, SWT.NONE);
+        fTimeGraphContentProvider = new FlameGraphContentProvider();
+        fPresentationProvider = new FlameGraphPresentationProvider();
+        fTimeGraphViewer.setTimeGraphContentProvider(fTimeGraphContentProvider);
+        fTimeGraphViewer.setTimeGraphProvider(fPresentationProvider);
+        IEditorPart editor = getSite().getPage().getActiveEditor();
+        if (editor instanceof ITmfTraceEditor) {
+            ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
+            if (trace != null) {
+                traceSelected(new TmfTraceSelectedSignal(this, trace));
+            }
+        }
+    }
+
+    /**
+     * Signal updated
+     *
+     * @param sig
+     *            signal
+     */
+    @TmfSignalHandler
+    public void selectionUpdated(TmfSelectionRangeUpdatedSignal sig) {
+        fTrace = TmfTraceManager.getInstance().getActiveTrace();
+        if (fTrace != null) {
+            CallGraphAnalysis flamegraphModule = TmfTraceUtils.getAnalysisModuleOfClass(fTrace, CallGraphAnalysis.class, CallGraphAnalysisUI.ID);
+            buildFlameGraph(flamegraphModule);
+        }
+    }
+
+    /**
+     * Handler for the trace opened signal
+     *
+     * @param signal
+     *            The incoming signal
+     */
+    @TmfSignalHandler
+    public void TraceOpened(TmfTraceOpenedSignal signal) {
+        fTrace = signal.getTrace();
+        if (fTrace != null) {
+            CallGraphAnalysis flamegraphModule = TmfTraceUtils.getAnalysisModuleOfClass(fTrace, CallGraphAnalysis.class, CallGraphAnalysisUI.ID);
+            buildFlameGraph(flamegraphModule);
+        }
+    }
+
+    /**
+     * Handler for the trace selected signal
+     *
+     * @param signal
+     *            The incoming signal
+     */
+    @TmfSignalHandler
+    public void traceSelected(final TmfTraceSelectedSignal signal) {
+        fTrace = signal.getTrace();
+        if (fTrace != null) {
+            CallGraphAnalysis flamegraphModule = TmfTraceUtils.getAnalysisModuleOfClass(fTrace, CallGraphAnalysis.class, CallGraphAnalysisUI.ID);
+            buildFlameGraph(flamegraphModule);
+        }
+    }
+
+    /**
+     * Get the necessary data for the flame graph and display it
+     *
+     * @param flamegraphModule
+     *            the callGraphAnalysis
+     */
+    private void buildFlameGraph(CallGraphAnalysis callGraphAnalysis) {
+        fTimeGraphViewer.setInput(null);
+        callGraphAnalysis.schedule();
+        Job j = new Job(Messages.CallGraphAnalysis_Execution) {
+
+            @Override
+            protected IStatus run(IProgressMonitor monitor) {
+                if (monitor.isCanceled()) {
+                    return Status.CANCEL_STATUS;
+                }
+                callGraphAnalysis.waitForCompletion(monitor);
+                Display.getDefault().asyncExec(() -> {
+                    fTimeGraphViewer.setInput(callGraphAnalysis.getThreadNodes());
+                });
+                return Status.OK_STATUS;
+            }
+        };
+        j.schedule();
+    }
+
+    /**
+     * Trace is closed: clear the data structures and the view
+     *
+     * @param signal
+     *            the signal received
+     */
+    @TmfSignalHandler
+    public void traceClosed(final TmfTraceClosedSignal signal) {
+        if (signal.getTrace() == fTrace) {
+            fTimeGraphViewer.setInput(null);
+        }
+    }
+
+    @Override
+    public void setFocus() {
+        fTimeGraphViewer.setFocus();
+    }
+
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlamegraphDepthEntry.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlamegraphDepthEntry.java
new file mode 100644 (file)
index 0000000..21ed20a
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph;
+
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
+
+/**
+ * An entry, or row, in the flame Graph view
+ *
+ * @author Sonia Farrah
+ */
+public class FlamegraphDepthEntry extends TimeGraphEntry {
+
+    private final int fDepth;
+
+    /**
+     * Constructor
+     *
+     * @param name
+     *            name of an entry
+     * @param startTime
+     *            Start time of an entry
+     * @param endTime
+     *            The end time of an entry
+     * @param depth
+     *            The Depth of an entry
+     */
+    public FlamegraphDepthEntry(String name, long startTime, long endTime, int depth) {
+        super(name, startTime, endTime);
+        fDepth = depth;
+    }
+
+    /**
+     * The depth of a flame graph entry
+     *
+     * @return The depth of a flame graph entry
+     */
+    public int getDepth() {
+        return fDepth;
+    }
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlamegraphEvent.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlamegraphEvent.java
new file mode 100644 (file)
index 0000000..5879483
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph;
+
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
+
+/**
+ * Time Event implementation specific to the FlameGraph View (it represents a
+ * function in a certain depth)
+ *
+ * @author Sonia Farrah
+ *
+ */
+public class FlamegraphEvent extends TimeEvent {
+
+    private final Object fSymbol;
+    private final int fNbCalls;
+    private final long fSelfTime;
+
+    /**
+     * Constructor
+     *
+     * @param source
+     *            The Entry
+     * @param beginTime
+     *            The event's begin time
+     * @param totalTime
+     *            The event's total time
+     * @param value
+     *            The event's value
+     * @param symbol
+     *            The event's address or name
+     * @param nbCalls
+     *            The event's number of calls
+     * @param selfTime
+     *            The event's self time
+     */
+    public FlamegraphEvent(ITimeGraphEntry source, long beginTime, long totalTime, int value, Object symbol, int nbCalls, long selfTime) {
+        super(source, beginTime, totalTime, value);
+        fSymbol = symbol;
+        fNbCalls = nbCalls;
+        fSelfTime = selfTime;
+    }
+
+    /**
+     * The event's name or address
+     *
+     * @return The event's name or address
+     */
+    public Object getSymbol() {
+        return fSymbol;
+    }
+
+    /**
+     * The event's number of calls
+     *
+     * @return The event's number of a calls
+     */
+    public int getNbCalls() {
+        return fNbCalls;
+    }
+
+    /**
+     * The self time of an event
+     *
+     * @return The self time
+     */
+    public long getSelfTime() {
+        return fSelfTime;
+    }
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/Messages.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/Messages.java
new file mode 100644 (file)
index 0000000..ebce3c4
--- /dev/null
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.analysis.timing.ui.flamegraph;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Message bundle for the flame graph view
+ *
+ * @author Sonia Farrah
+ */
+public class Messages extends NLS {
+    private static final String BUNDLE_NAME = Messages.class.getPackage().getName() + ".messages"; //$NON-NLS-1$
+    /**
+     * The duration of a function
+     */
+    public static String FlameGraph_Duration;
+    /**
+     * The time percentage of a function
+     */
+    public static String FlameGraph_Percentage;
+    /**
+     * The number of calls of a function
+     */
+    public static String FlameGraph_NbCalls;
+    /**
+     * The self time of a function
+     */
+    public static String FlameGraph_SelfTime;
+    /**
+     * The depth of a function
+     */
+    public static String FlameGraph_Depth;
+    /**
+     * Execution of the callGraph Analysis
+     */
+    public static String CallGraphAnalysis_Execution;
+
+    static {
+        // initialize resource bundle
+        NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+    }
+
+    private Messages() {
+    }
+}
\ No newline at end of file
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/messages.properties b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/messages.properties
new file mode 100644 (file)
index 0000000..be0ba1d
--- /dev/null
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2016 Ericsson
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+###############################################################################
+FlameGraph_Duration=Duration
+FlameGraph_Percentage=Percentage
+FlameGraph_NbCalls=Number of calls
+FlameGraph_SelfTime=Self time
+FlameGraph_Depth=Depth
+CallGraphAnalysis_Execution=CallGraphAnalysis execution
index 2e9165a597904db9bd86bcfa22942c15db587fab..9af91a621d5406bcd953467315b2b29a22857fe4 100644 (file)
@@ -16,8 +16,8 @@ import java.util.Set;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.tracecompass.lttng2.ust.core.trace.layout.ILttngUstEventLayout;
-import org.eclipse.tracecompass.tmf.core.analysis.requirements.TmfAnalysisEventFieldRequirement;
 import org.eclipse.tracecompass.tmf.core.analysis.requirements.TmfAbstractAnalysisRequirement;
+import org.eclipse.tracecompass.tmf.core.analysis.requirements.TmfAnalysisEventFieldRequirement;
 import org.eclipse.tracecompass.tmf.core.analysis.requirements.TmfCompositeAnalysisRequirement;
 
 import com.google.common.collect.ImmutableSet;
index bdcc3ad89f55cb8ad7b608d94654e956c56e3ca3..e1f176bff836df0beb67e80cef2825d3295803be 100644 (file)
@@ -11,21 +11,69 @@ package org.eclipse.tracecompass.internal.lttng2.ust.ui.analysis.callstack;
 import org.eclipse.osgi.util.NLS;
 
 /**
- * Message bundle for the ust memory analysis module
+ * Message bundle for the call stack analysis module
  *
- * @author Bernd Hufmann
+ * @author Sonia Farrah
  */
+
 public class Messages extends NLS {
     private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.lttng2.ust.ui.analysis.callstack.messages"; //$NON-NLS-1$
 
-    /** Information regarding events loading prior to the analysis execution */
-    public static String LttnUstCallStackAnalysisModule_EventsLoadingInformation;
+    /**
+     * Self time of a function
+     */
+    public static String SegmentStoreStaticsViewer_selfTime;
+    /**
+    * Total time of a function
+    */
+    public static String SegmentStoreStaticsViewer_totalTime;
+
+    /**
+    * Adress of a function
+    */
+    public static String Function_address;
+    /**
+     * Total self Time of a function
+     */
+    public static String SegmentStoreStaticsViewer_totalSelfTime;
+
+    /**
+     * Total calls of a function
+     */
+    public static String SegmentStoreStaticsViewer_totalCalls;
+    /**
+     *The callers of a function
+     */
+    public static String SegmentStoreStaticsViewer_Callers;
+    /**
+     *The callees of a function
+     */
+    public static String SegmentStoreStaticsViewer_Callees;
+    /**
+     *The depth of a function
+     */
+    public static String SegmentStoreStaticsViewer_Depth;
+    /**
+     *The duration of a function
+     */
+    public static String FlameGraph_Duration;
+    /**
+     *The time percentage of a function
+     */
+    public static String FlameGraph_Percentage;
+    /**
+     *The number of calls of a function
+     */
+    public static String FlameGraph_NbreCalls;
 
     static {
         // initialize resource bundle
         NLS.initializeMessages(BUNDLE_NAME, Messages.class);
     }
 
+    /** Information regarding events loading prior to the analysis execution */
+    public static String LttnUstCallStackAnalysisModule_EventsLoadingInformation;
+
     private Messages() {
     }
 }
index a5e29a87afe380f1b3bbb514c27f13e476668cc3..330002928e45067b54b1916550cb690396551ec3 100644 (file)
@@ -5,8 +5,23 @@
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
 # http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     Ericsson - Initial API and implementation
 ###############################################################################
 LttnUstCallStackAnalysisModule_EventsLoadingInformation=Add the ''vtid'' and ''procname'' contexts to your trace session. \n\
 Preload the ''liblttng-ust-cyg-profile'' library when running your program: \n\
 LD_PRELOAD=/usr/lib/liblttng-ust-cyg-profile.so ./myprogram
 
+SegmentStoreStaticsViewer_selfTime=Self time
+SegmentStoreStaticsViewer_totalTime=Total time
+Function_address=address
+FlameGraph_Duration=Duration
+FlameGraph_Percentage=Percentage
+FlameGraph_NbreCalls=Number of calls
+
+SegmentStoreStaticsViewer_totalSelfTime=Total self time
+SegmentStoreStaticsViewer_totalCalls=Total calls
+SegmentStoreStaticsViewer_Callers=Callers
+SegmentStoreStaticsViewer_Callees=Callees
+SegmentStoreStaticsViewer_Depth=Depth
This page took 0.039476 seconds and 5 git commands to generate.