tmf.ui: move optimization algorithm out into its own file.
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Wed, 3 Aug 2016 17:37:57 +0000 (13:37 -0400)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Wed, 3 Aug 2016 22:31:57 +0000 (18:31 -0400)
This also adds a bit more javadoc explaining how the algorithm works.

Change-Id: I74f5bdb163e7cfa1aee7181a9b3a4b30c0cc86d7
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/78399
Reviewed-by: Jean-Christian Kouame <jean-christian.kouame@ericsson.com>
Tested-by: Jean-Christian Kouame <jean-christian.kouame@ericsson.com>
Reviewed-by: Hudson CI
analysis/org.eclipse.tracecompass.analysis.os.linux.ui.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/tests/view/controlflow/ControlFlowOptimizerTest.java
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowView.java
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/NaiveOptimizationAlgorithm.java [new file with mode: 0644]

index f81d88e7238ddc101df82d1e9405c19f4b7db213..d6a9df71691a113e602c6ecdbefbb7f5eb580756 100644 (file)
@@ -24,8 +24,7 @@ import java.util.function.Function;
 
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowEntry;
-import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowView;
-import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowView.OptimizationAlgorithm;
+import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.NaiveOptimizationAlgorithm;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.ctf.core.trace.CtfTmfTrace;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
@@ -58,8 +57,8 @@ public class ControlFlowOptimizerTest {
      *
      * @return the optimization method to test.
      */
-    protected OptimizationAlgorithm getOptimizationMethod() {
-        return new ControlFlowView.OptimizationAlgorithm();
+    protected Function<Collection<ILinkEvent>, Map<Integer, Long>> getOptimizationMethod() {
+        return new NaiveOptimizationAlgorithm();
     }
 
     /**
index fe8535b0752ef1e103c2c754c6731577d847ec96..1b3f0f519835924faa5931e1c5e60bdc15b015ad 100644 (file)
@@ -21,7 +21,6 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -87,10 +86,7 @@ import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
 
-import com.google.common.collect.HashMultiset;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Multiset;
-import com.google.common.collect.Multisets;
 
 /**
  * The Control Flow view main object
@@ -136,7 +132,7 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
 
     private static final Comparator<ITimeGraphEntry>[] COLUMN_COMPARATORS;
 
-    private final Function<Collection<ILinkEvent>, Map<Integer, Long>> UPDATE_SCHEDULING_COLUMN_ALGO = new OptimizationAlgorithm();
+    private final Function<Collection<ILinkEvent>, Map<Integer, Long>> UPDATE_SCHEDULING_COLUMN_ALGO = new NaiveOptimizationAlgorithm();
 
     private static final int INITIAL_SORT_COLUMN_INDEX = 3;
 
@@ -498,80 +494,6 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView {
 
     }
 
-    /**
-     * Optimization algorithm, overridable.
-     *
-     * @author Matthew Khouzam
-     * @author Samuel Gagnon
-     */
-    public static class OptimizationAlgorithm implements Function<Collection<ILinkEvent>, Map<Integer, Long>> {
-
-        /**
-         * Get the scheduling column order by arrows
-         *
-         * @param arrows
-         *            the list of visible links
-         * @return the list of weights, by thread ID
-         */
-        @Override
-        public Map<Integer, Long> apply(Collection<ILinkEvent> arrows) {
-            /*
-             * "transitions" contains the count of every arrows between two tids
-             * (Pair<Integer, Integer>). For constructing the Pair, we always
-             * put the smallest tid first
-             */
-            Multiset<Pair<Integer, Integer>> transitions = HashMultiset.<Pair<Integer,Integer>>create();
-
-            /*
-             * We iterate in arrows to count the number of transitions between
-             * every pair (tid,tid) in the current view
-             */
-            for (ILinkEvent arrow : arrows) {
-                ITimeGraphEntry from = arrow.getEntry();
-                ITimeGraphEntry to = arrow.getDestinationEntry();
-                if (!(from instanceof ControlFlowEntry) || !(to instanceof ControlFlowEntry)) {
-                    continue;
-                }
-                int fromTid = ((ControlFlowEntry) from).getThreadId();
-                int toTid = ((ControlFlowEntry) to).getThreadId();
-                if (fromTid != toTid) {
-                    Pair<Integer, Integer> key = new Pair<>(Math.min(fromTid, toTid), Math.max(fromTid, toTid));
-                    transitions.add(key);
-                }
-            }
-
-            /*
-             * We now have a transition count for every pair (tid,tid). The next
-             * step is to sort every pair according to its count in decreasing
-             * order
-             */
-            List<Pair<Integer, Integer>> sortedTransitionsByCount = Multisets.copyHighestCountFirst(transitions).asList();
-
-            /*
-             * Next, we find the order in which we want to display our threads.
-             * We simply iterate in every pair (tid,tid) in orderedTidList. Each
-             * time we see a new tid, we add it at the end of orderedTidList.
-             * This way, threads with lots of transitions will be grouped in the
-             * top. While very naive, this algorithm is fast, simple and gives
-             * decent results.
-             */
-            Map<Integer, Long> orderedTidMap = new LinkedHashMap<>();
-            long pos = 0;
-            for (Pair<Integer, Integer> threadPair : sortedTransitionsByCount) {
-                if (orderedTidMap.get(threadPair.getFirst()) == null) {
-                    orderedTidMap.put(threadPair.getFirst(), pos);
-                    pos++;
-                }
-                if (orderedTidMap.get(threadPair.getSecond()) == null) {
-                    orderedTidMap.put(threadPair.getSecond(), pos);
-                    pos++;
-                }
-            }
-
-            return orderedTidMap;
-        }
-    }
-
     /**
      * @author gbastien
      *
diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/NaiveOptimizationAlgorithm.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/NaiveOptimizationAlgorithm.java
new file mode 100644 (file)
index 0000000..f3f11f2
--- /dev/null
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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.os.linux.ui.views.controlflow;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import org.eclipse.tracecompass.tmf.core.util.Pair;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
+import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import com.google.common.collect.Multisets;
+
+/**
+ * Optimization algorithm, this approach bubbles up the elements that have more
+ * connections together. This effectively will give good results with a
+ * complexity of O(n) where n is the number of transitions. It may solve
+ * non-optimally for very tightly coupled cliques.
+ *
+ * @author Matthew Khouzam
+ * @author Samuel Gagnon
+ */
+public class NaiveOptimizationAlgorithm implements Function<Collection<ILinkEvent>, Map<Integer, Long>> {
+
+    /**
+     * Get the scheduling column order by arrows
+     *
+     * @param arrows
+     *            the list of visible links
+     * @return the list of weights, by thread ID
+     */
+    @Override
+    public Map<Integer, Long> apply(Collection<ILinkEvent> arrows) {
+        /*
+         * "transitions" contains the count of every arrows between two tids
+         * (Pair<Integer, Integer>). For constructing the Pair, we always put
+         * the smallest tid first
+         */
+        Multiset<Pair<Integer, Integer>> transitions = HashMultiset.<Pair<Integer, Integer>> create();
+
+        /*
+         * We iterate in arrows to count the number of transitions between every
+         * pair (tid,tid) in the current view
+         */
+        for (ILinkEvent arrow : arrows) {
+            ITimeGraphEntry from = arrow.getEntry();
+            ITimeGraphEntry to = arrow.getDestinationEntry();
+            if (!(from instanceof ControlFlowEntry) || !(to instanceof ControlFlowEntry)) {
+                continue;
+            }
+            int fromTid = ((ControlFlowEntry) from).getThreadId();
+            int toTid = ((ControlFlowEntry) to).getThreadId();
+            if (fromTid != toTid) {
+                Pair<Integer, Integer> key = new Pair<>(Math.min(fromTid, toTid), Math.max(fromTid, toTid));
+                transitions.add(key);
+            }
+        }
+
+        /*
+         * We now have a transition count for every pair (tid,tid). The next
+         * step is to sort every pair according to its count in decreasing order
+         */
+        List<Pair<Integer, Integer>> sortedTransitionsByCount = Multisets.copyHighestCountFirst(transitions).asList();
+
+        /*
+         * Next, we find the order in which we want to display our threads. We
+         * simply iterate in every pair (tid,tid) in orderedTidList. Each time
+         * we see a new tid, we add it at the end of orderedTidList. This way,
+         * threads with lots of transitions will be grouped in the top. While
+         * very naive, this algorithm is fast, simple and gives decent results.
+         */
+        Map<Integer, Long> orderedTidMap = new LinkedHashMap<>();
+        long pos = 0;
+        for (Pair<Integer, Integer> threadPair : sortedTransitionsByCount) {
+            if (orderedTidMap.get(threadPair.getFirst()) == null) {
+                orderedTidMap.put(threadPair.getFirst(), pos);
+                pos++;
+            }
+            if (orderedTidMap.get(threadPair.getSecond()) == null) {
+                orderedTidMap.put(threadPair.getSecond(), pos);
+                pos++;
+            }
+        }
+
+        return orderedTidMap;
+    }
+}
\ No newline at end of file
This page took 0.029862 seconds and 5 git commands to generate.