timing: support sorting by thread name or ID in Flame Graphs
authorBernd Hufmann <Bernd.Hufmann@ericsson.com>
Tue, 16 Aug 2016 13:29:15 +0000 (09:29 -0400)
committerBernd Hufmann <bernd.hufmann@ericsson.com>
Tue, 23 Aug 2016 21:39:31 +0000 (17:39 -0400)
This will add 2 buttons for switching the sort order between
thread name and thread ID.

Change-Id: I4a258710f7b147520077d29c90fdedb34ce8d576
Signed-off-by: Bernd Hufmann <Bernd.Hufmann@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/79159
Reviewed-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Tested-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewed-by: Hudson CI
analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_alpha.gif [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_alpha_rev.gif [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_num.gif [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_num_rev.gif [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphContentProvider.java
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/FlameGraphView.java
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/Messages.java
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/SortOption.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/ThreadIdComparator.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/ThreadNameComparator.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/messages.properties

diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_alpha.gif b/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_alpha.gif
new file mode 100644 (file)
index 0000000..6311cc0
Binary files /dev/null and b/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_alpha.gif differ
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_alpha_rev.gif b/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_alpha_rev.gif
new file mode 100644 (file)
index 0000000..7503bf1
Binary files /dev/null and b/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_alpha_rev.gif differ
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_num.gif b/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_num.gif
new file mode 100644 (file)
index 0000000..a889504
Binary files /dev/null and b/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_num.gif differ
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_num_rev.gif b/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_num_rev.gif
new file mode 100644 (file)
index 0000000..2df6cac
Binary files /dev/null and b/analysis/org.eclipse.tracecompass.analysis.timing.ui/icons/etool16/sort_num_rev.gif differ
index f38a28c71a92aceab4b840abcb040e8b0ddf8ecc..d7361665adbc069c9e9caa27f1469fe4581e4ea5 100644 (file)
@@ -9,14 +9,17 @@
 
 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;
@@ -25,8 +28,6 @@ import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphContentProvid
 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
  *
@@ -38,6 +39,9 @@ public class FlameGraphContentProvider implements ITimeGraphContentProvider {
     private List<FlamegraphDepthEntry> fFlameGraphEntries = new ArrayList<>();
     private long fThreadDuration;
     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
@@ -57,7 +61,7 @@ public class FlameGraphContentProvider implements ITimeGraphContentProvider {
                 childrenEntries.add(entry);
             }
         }
-        FlamegraphDepthEntry firstEntry = NonNullUtils.checkNotNull(childrenEntries.get(0));
+        FlamegraphDepthEntry firstEntry = checkNotNull(childrenEntries.get(0));
         firstEntry.addEvent(new FlamegraphEvent(firstEntry, timestampStack.peek(), firstNode));
         // Build the event list for next entries (next depth)
         addEvent(firstNode, childrenEntries, timestampStack);
@@ -88,7 +92,7 @@ public class FlameGraphContentProvider implements ITimeGraphContentProvider {
                 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));
@@ -117,8 +121,8 @@ public class FlameGraphContentProvider implements ITimeGraphContentProvider {
                 }
             }
         }
-        // Reverse the order of threads
-        fFlameGraphEntries = Lists.reverse(fFlameGraphEntries);
+        // Sort the threads
+        fFlameGraphEntries.sort(fThreadComparator);
         return fFlameGraphEntries.toArray(new ITimeGraphEntry[fFlameGraphEntries.size()]);
     }
 
@@ -172,4 +176,40 @@ public class FlameGraphContentProvider implements ITimeGraphContentProvider {
         // 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;
+        }
+    }
 }
index 702225b8668ae5ccf2ab74f3d5741525cd96c8b7..695c0f00d0298727450ad4718ab824724899d85a 100644 (file)
@@ -18,9 +18,14 @@ import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.GroupMarker;
+import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.action.IMenuListener;
 import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
 import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.swt.SWT;
@@ -30,6 +35,7 @@ import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Menu;
 import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.CallGraphAnalysis;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator;
 import org.eclipse.tracecompass.internal.analysis.timing.ui.callgraph.CallGraphAnalysisUI;
 import org.eclipse.tracecompass.segmentstore.core.ISegment;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
@@ -45,6 +51,7 @@ 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.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl;
+import org.eclipse.ui.IActionBars;
 import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.IWorkbenchActionConstants;
 
@@ -61,6 +68,13 @@ public class FlameGraphView extends TmfView {
      */
     public static final String ID = FlameGraphView.class.getPackage().getName() + ".flamegraphView"; //$NON-NLS-1$
 
+    private static final String SORT_OPTION_KEY = "sort.option"; //$NON-NLS-1$
+    private static final ImageDescriptor SORT_BY_NAME_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha.gif"); //$NON-NLS-1$
+    private static final ImageDescriptor SORT_BY_NAME_REV_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha_rev.gif"); //$NON-NLS-1$
+    private static final ImageDescriptor SORT_BY_ID_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_num.gif"); //$NON-NLS-1$
+    private static final ImageDescriptor SORT_BY_ID_REV_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_num_rev.gif"); //$NON-NLS-1$
+
+
     private TimeGraphViewer fTimeGraphViewer;
 
     private FlameGraphContentProvider fTimeGraphContentProvider;
@@ -70,6 +84,8 @@ public class FlameGraphView extends TmfView {
     private ITmfTrace fTrace;
 
     private final @NonNull MenuManager fEventMenuManager = new MenuManager();
+    private Action fSortByNameAction;
+    private Action fSortByIdAction;
 
     /**
      * Constructor
@@ -93,10 +109,14 @@ public class FlameGraphView extends TmfView {
                 traceSelected(new TmfTraceSelectedSignal(this, trace));
             }
         }
+        contributeToActionBars();
+        loadSortOption();
+
         getSite().setSelectionProvider(fTimeGraphViewer.getSelectionProvider());
         createTimeEventContextMenu();
     }
 
+
     /**
      * Handler for the trace opened signal
      *
@@ -171,6 +191,10 @@ public class FlameGraphView extends TmfView {
         fTimeGraphViewer.setFocus();
     }
 
+    // ------------------------------------------------------------------------
+    // Helper methods
+    // ------------------------------------------------------------------------
+
     private void createTimeEventContextMenu() {
         fEventMenuManager.setRemoveAllWhenShown(true);
         TimeGraphControl timeGraphControl = fTimeGraphViewer.getTimeGraphControl();
@@ -245,4 +269,103 @@ public class FlameGraphView extends TmfView {
             }
         }
     }
+
+    private void contributeToActionBars() {
+        IActionBars bars = getViewSite().getActionBars();
+        fillLocalToolBar(bars.getToolBarManager());
+    }
+
+    private void fillLocalToolBar(IToolBarManager manager) {
+        manager.add(getSortByNameAction());
+        manager.add(getSortByIdAction());
+        manager.add(new Separator());
+    }
+
+    private Action getSortByNameAction() {
+        if (fSortByNameAction == null) {
+            fSortByNameAction = new Action(Messages.FlameGraph_SortByThreadName, IAction.AS_CHECK_BOX) {
+                @Override
+                public void run() {
+                    SortOption sortOption = fTimeGraphContentProvider.getSortOption();
+                    if (sortOption == SortOption.BY_NAME) {
+                        setSortOption(SortOption.BY_NAME_REV);
+                    } else {
+                        setSortOption(SortOption.BY_NAME);
+                    }
+                }
+            };
+            fSortByNameAction.setToolTipText(Messages.FlameGraph_SortByThreadName);
+            fSortByNameAction.setImageDescriptor(SORT_BY_NAME_ICON);
+        }
+        return fSortByNameAction;
+    }
+
+    private Action getSortByIdAction() {
+        if (fSortByIdAction == null) {
+            fSortByIdAction = new Action(Messages.FlameGraph_SortByThreadId, IAction.AS_CHECK_BOX) {
+                @Override
+                public void run() {
+                    SortOption sortOption = fTimeGraphContentProvider.getSortOption();
+                    if (sortOption == SortOption.BY_ID) {
+                        setSortOption(SortOption.BY_ID_REV);
+                    } else {
+                        setSortOption(SortOption.BY_ID);
+                    }
+                }
+            };
+            fSortByIdAction.setToolTipText(Messages.FlameGraph_SortByThreadId);
+            fSortByIdAction.setImageDescriptor(SORT_BY_ID_ICON);
+        }
+        return fSortByIdAction;
+    }
+
+    private void setSortOption(SortOption sortOption) {
+        // reset defaults
+        getSortByNameAction().setChecked(false);
+        getSortByNameAction().setImageDescriptor(SORT_BY_NAME_ICON);
+        getSortByIdAction().setChecked(false);
+        getSortByIdAction().setImageDescriptor(SORT_BY_ID_ICON);
+
+        if (sortOption.equals(SortOption.BY_NAME)) {
+            fTimeGraphContentProvider.setSortOption(SortOption.BY_NAME);
+            getSortByNameAction().setChecked(true);
+        } else if (sortOption.equals(SortOption.BY_NAME_REV)) {
+            fTimeGraphContentProvider.setSortOption(SortOption.BY_NAME_REV);
+            getSortByNameAction().setChecked(true);
+            getSortByNameAction().setImageDescriptor(SORT_BY_NAME_REV_ICON);
+        } else if (sortOption.equals(SortOption.BY_ID)) {
+            fTimeGraphContentProvider.setSortOption(SortOption.BY_ID);
+            getSortByIdAction().setChecked(true);
+        } else if (sortOption.equals(SortOption.BY_ID_REV)) {
+            fTimeGraphContentProvider.setSortOption(SortOption.BY_ID_REV);
+            getSortByIdAction().setChecked(true);
+            getSortByIdAction().setImageDescriptor(SORT_BY_ID_REV_ICON);
+        }
+        saveSortOption();
+        fTimeGraphViewer.refresh();
+    }
+
+    private void saveSortOption() {
+        SortOption sortOption = fTimeGraphContentProvider.getSortOption();
+        IDialogSettings settings = Activator.getDefault().getDialogSettings();
+        IDialogSettings section = settings.getSection(getClass().getName());
+        if (section == null) {
+            section = settings.addNewSection(getClass().getName());
+        }
+        section.put(SORT_OPTION_KEY, sortOption.name());
+    }
+
+    private void loadSortOption() {
+        IDialogSettings settings = Activator.getDefault().getDialogSettings();
+        IDialogSettings section = settings.getSection(getClass().getName());
+        if (section == null) {
+            return;
+        }
+        String sortOption = section.get(SORT_OPTION_KEY);
+        if (sortOption == null) {
+            return;
+        }
+        setSortOption(SortOption.fromName(sortOption));
+    }
+
 }
index c1d249ca998656dd4dc862f558e79d3f1ef1b8f3..f985d9ddbcb62e3018ca6d7b6cbca699654a1fdc 100644 (file)
@@ -85,6 +85,14 @@ public class Messages extends NLS {
      * Go to minimum duration
      */
     public static String FlameGraphView_GotoMinDuration;
+    /**
+     * The action name for sorting by thread name
+     */
+    public static String FlameGraph_SortByThreadName;
+    /**
+     * The action name for sorting by thread name
+     */
+    public static String FlameGraph_SortByThreadId;
     /**
      * Execution of the callGraph Analysis
      */
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/SortOption.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/SortOption.java
new file mode 100644 (file)
index 0000000..d539b2f
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * The sort option enum
+ *
+ * @author Bernd Hufmann
+ */
+enum SortOption {
+    /** Sort by thread name*/
+    BY_NAME,
+    /** Sort by thread name reverse */
+    BY_NAME_REV,
+    /** Sort by thread ID */
+    BY_ID,
+    /** Sort by thread ID reverse*/
+    BY_ID_REV;
+
+    public static SortOption fromName(String name) {
+        if (name.equals(SortOption.BY_NAME.name())) {
+            return SortOption.BY_NAME;
+        } else if (name.equals(SortOption.BY_NAME_REV.name())) {
+            return SortOption.BY_NAME_REV;
+        } else if (name.equals(SortOption.BY_ID.name())) {
+            return SortOption.BY_ID;
+        } else if (name.equals(SortOption.BY_ID_REV.name())) {
+            return SortOption.BY_ID_REV;
+        }
+        return SortOption.BY_NAME;
+    }
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/ThreadIdComparator.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/ThreadIdComparator.java
new file mode 100644 (file)
index 0000000..7180fc1
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * 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.Comparator;
+
+/**
+ * Comparator to compare by thread name.
+ *
+ * @author Bernd Hufmann
+ *
+ */
+class ThreadIdComparator implements Comparator<FlamegraphDepthEntry> {
+    @Override
+    public int compare(FlamegraphDepthEntry o1, FlamegraphDepthEntry o2) {
+        return Long.compare(o1.getId(), o2.getId());
+    }
+}
diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/ThreadNameComparator.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/flamegraph/ThreadNameComparator.java
new file mode 100644 (file)
index 0000000..2e6bcde
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * 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.Comparator;
+
+/**
+ * Comparator to compare by thread name.
+ *
+ * @author Bernd Hufmann
+ *
+ */
+class ThreadNameComparator implements Comparator<FlamegraphDepthEntry> {
+    @Override
+    public int compare(FlamegraphDepthEntry o1, FlamegraphDepthEntry o2) {
+        return o1.getName().compareTo(o2.getName());
+    }
+}
index 41386dc3bf327c730610864e532370911329efdd..9ef7c591beb1da17a172035c3572c2e6fbed312a 100644 (file)
@@ -23,4 +23,6 @@ FlameGraph_Durations=Durations
 FlameGraph_SelfTimes=Self times
 FlameGraphView_GotoMaxDuration=Go to maximum
 FlameGraphView_GotoMinDuration=Go to minimum
+FlameGraph_SortByThreadName=Sort threads by thread name
+FlameGraph_SortByThreadId=Sort threads by thread id
 CallGraphAnalysis_Execution=CallGraphAnalysis execution
This page took 0.03286 seconds and 5 git commands to generate.