summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorCamilo Bernal2013-03-07 16:17:07 (EST)
committer Roland Grunberg2013-04-11 16:48:18 (EDT)
commit836354a817a2d075eed9b30a6fcec7401521fbf0 (patch)
tree6be73a820d37547cb26024f2f26b902e2b269354
parent782e74805731d369f2da16dacd6fd001471b9e8d (diff)
downloadorg.eclipse.linuxtools-836354a817a2d075eed9b30a6fcec7401521fbf0.zip
org.eclipse.linuxtools-836354a817a2d075eed9b30a6fcec7401521fbf0.tar.gz
org.eclipse.linuxtools-836354a817a2d075eed9b30a6fcec7401521fbf0.tar.bz2
Add support for comparing perf stat sessionsrefs/changes/22/11122/11
* Abstract class containing common comparison functionality. * Perf stat diff handler. * Perf stat diff view. * Comparison data class to handle stat data comparison. * Stat entry class to represent an entry in a perf stat report. * Add tests for PMStatEntry. * Remove secondary id from stat view. Change-Id: I0cb8c9015051c975b10821bd772651a2e45b67f7 Reviewed-on: https://git.eclipse.org/r/11122 Reviewed-by: Roland Grunberg <rgrunber@redhat.com> IP-Clean: Roland Grunberg <rgrunber@redhat.com> Tested-by: Roland Grunberg <rgrunber@redhat.com>
-rw-r--r--perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_diff.stat7
-rw-r--r--perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_new.stat9
-rw-r--r--perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_old.stat9
-rw-r--r--perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_simple.stat8
-rw-r--r--perf/org.eclipse.linuxtools.perf.tests/src/org/eclipse/linuxtools/internal/perf/tests/AllPerfTests.java1
-rw-r--r--perf/org.eclipse.linuxtools.perf.tests/src/org/eclipse/linuxtools/internal/perf/tests/StatsComparisonTest.java178
-rw-r--r--perf/org.eclipse.linuxtools.perf/plugin.xml21
-rw-r--r--perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/PerfPlugin.java47
-rw-r--r--perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/StatComparisonData.java233
-rw-r--r--perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/AbstractComparisonHandler.java202
-rw-r--r--perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/Messages.java13
-rw-r--r--perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/PerfSaveSessionHandler.java3
-rw-r--r--perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/PerfStatsComparisonHandler.java49
-rw-r--r--perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/messages.properties15
-rw-r--r--perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/model/PMStatEntry.java217
-rw-r--r--perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/ui/StatComparisonView.java142
-rw-r--r--perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/ui/StatView.java22
17 files changed, 1164 insertions, 12 deletions
diff --git a/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_diff.stat b/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_diff.stat
new file mode 100644
index 0000000..8a4e251
--- /dev/null
+++ b/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_diff.stat
@@ -0,0 +1,7 @@
+ -4.0 cpu-clock # 0.000 ( +- 0.54% )
+ -2000.0 page-faults # -0.310 M/sec ( +- 0.02% )
+ 0.0 context-switches # -0.130 K/sec ( +- 36.34% )
+ -1000.0 minor-faults # -0.300 M/sec ( +- 0.02% )
+ 0.0 major-faults # 0.000 K/sec ( +- 0.00% )
+
+ -0.008 seconds time elapsed # 0.000 ( +- 0.92% ) \ No newline at end of file
diff --git a/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_new.stat b/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_new.stat
new file mode 100644
index 0000000..58aa40f
--- /dev/null
+++ b/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_new.stat
@@ -0,0 +1,9 @@
+ Performance counter stats for '/home/camilo/runtime-EclipseApplication/fib/Debug/fib' (5 runs):
+
+ 4.781967 cpu-clock ( +- 0.17% )
+ 1,164 page-faults # 0.050 M/sec ( +- 0.01% )
+ 1 context-switches # 0.007 K/sec ( +- 19.67% )
+ 2,164 minor-faults # 0.060 M/sec ( +- 0.01% )
+ 0 major-faults # 0.000 K/sec
+
+ 0.000964180 seconds time elapsed ( +- 0.46% ) \ No newline at end of file
diff --git a/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_old.stat b/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_old.stat
new file mode 100644
index 0000000..c5bf631
--- /dev/null
+++ b/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_old.stat
@@ -0,0 +1,9 @@
+ Performance counter stats for '/home/camilo/runtime-EclipseApplication/fib/Debug/fib' (5 runs):
+
+ 8.781967 cpu-clock ( +- 0.37% )
+ 3,164 page-faults # 0.360 M/sec ( +- 0.01% )
+ 1 context-switches # 0.137 K/sec ( +- 16.67% )
+ 3,164 minor-faults # 0.360 M/sec ( +- 0.01% )
+ 0 major-faults # 0.000 K/sec
+
+ 0.008964180 seconds time elapsed ( +- 0.46% ) \ No newline at end of file
diff --git a/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_simple.stat b/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_simple.stat
new file mode 100644
index 0000000..50e787a
--- /dev/null
+++ b/perf/org.eclipse.linuxtools.perf.tests/resources/stat-data/perf_simple.stat
@@ -0,0 +1,8 @@
+ Performance counter stats for '/home/camilo/runtime-EclipseApplication/fib/Debug/fib' (5 runs):
+
+ 4.78 cpu-clock ( +- 0.37% )
+ 4.78 task-clock # 0.080 CPUs utilized ( +- 0.37% )
+ 1,164 page-faults # 0.050 M/sec ( +- 0.01% )
+ 2,164 minor-faults # 0.060 M/sec ( +- 0.01% )
+
+ 0.000964180 seconds time elapsed ( +- 0.46% ) \ No newline at end of file
diff --git a/perf/org.eclipse.linuxtools.perf.tests/src/org/eclipse/linuxtools/internal/perf/tests/AllPerfTests.java b/perf/org.eclipse.linuxtools.perf.tests/src/org/eclipse/linuxtools/internal/perf/tests/AllPerfTests.java
index 550a82b..a879cd1 100644
--- a/perf/org.eclipse.linuxtools.perf.tests/src/org/eclipse/linuxtools/internal/perf/tests/AllPerfTests.java
+++ b/perf/org.eclipse.linuxtools.perf.tests/src/org/eclipse/linuxtools/internal/perf/tests/AllPerfTests.java
@@ -32,6 +32,7 @@ public class AllPerfTests {
suite.addTestSuite(ModelTest.class);
suite.addTestSuite(DataManipulatorTest.class);
suite.addTestSuite(SaveSessionTest.class);
+ suite.addTestSuite(StatsComparisonTest.class);
if (RUN_PERF) {
suite.addTestSuite(LaunchTest.class);
diff --git a/perf/org.eclipse.linuxtools.perf.tests/src/org/eclipse/linuxtools/internal/perf/tests/StatsComparisonTest.java b/perf/org.eclipse.linuxtools.perf.tests/src/org/eclipse/linuxtools/internal/perf/tests/StatsComparisonTest.java
new file mode 100644
index 0000000..49b8403
--- /dev/null
+++ b/perf/org.eclipse.linuxtools.perf.tests/src/org/eclipse/linuxtools/internal/perf/tests/StatsComparisonTest.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc.
+ * 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
+ *
+ * Contributors:
+ * Camilo Bernal <cabernal@redhat.com> - Initial Implementation.
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.perf.tests;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.eclipse.linuxtools.internal.perf.StatComparisonData;
+import org.eclipse.linuxtools.internal.perf.model.PMStatEntry;
+
+import junit.framework.TestCase;
+
+public class StatsComparisonTest extends TestCase {
+ PMStatEntry statEntry;
+ PMStatEntry statEntry2;
+ PMStatEntry statEntry3;
+ PMStatEntry statEntry4;
+ private static final String STAT_RES = "resources/stat-data/";
+
+ @Override
+ protected void setUp() {
+ String event = "event";
+ String units = "unit";
+ float samples = 1;
+ float metrics = 2;
+ float deviation = 3;
+ float scaling = 4;
+
+ statEntry = new PMStatEntry(samples, event, metrics, units, deviation,
+ scaling);
+ statEntry2 = new PMStatEntry(samples, event, metrics, units, deviation,
+ scaling);
+ statEntry3 = new PMStatEntry(samples++, event, metrics++, units,
+ deviation++, scaling);
+ statEntry4 = new PMStatEntry(samples--, "event2", metrics--, units,
+ deviation--, scaling);
+ }
+
+ public void testPMStatEntryGetters() {
+ assertEquals("event", statEntry.getEvent());
+ assertEquals("unit", statEntry.getUnits());
+ assertEquals((float)1, statEntry.getSamples());
+ assertEquals((float)2, statEntry.getMetrics());
+ assertEquals((float)3, statEntry.getDeviation());
+ assertEquals((float)4, statEntry.getScaling());
+ }
+
+ public void testPMStatEntryEquality() {
+ assertTrue(statEntry.equalEvents(statEntry3));
+ assertFalse(statEntry.equalEvents(statEntry4));
+ assertTrue(statEntry.equals(statEntry2));
+ }
+
+ public void testPMStatEntryArray() {
+ String[] expectedList = new String[] {
+ String.valueOf(statEntry.getSamples()), statEntry.getEvent(),
+ String.valueOf(statEntry.getFormattedMetrics()), statEntry.getUnits(),
+ String.valueOf(statEntry.getFormattedDeviation()) };
+
+ String[] actualList = statEntry.toStringArray();
+
+ // test string array representation
+ assertTrue(Arrays.equals(expectedList, actualList));
+ }
+
+ public void testPMStatEntryComparison() {
+ String expectedEvent = "event";
+ String expectedUnits = "unit";
+ float expectedSamples = statEntry.getSamples() - statEntry2.getSamples();
+ float expectedMetrics = statEntry.getMetrics() - statEntry2.getMetrics();
+ float expectedDeviation = statEntry.getDeviation() + statEntry2.getDeviation();
+ float expectedScaling = statEntry.getScaling() + statEntry2.getScaling();
+
+ PMStatEntry expectedDiff = new PMStatEntry(expectedSamples,
+ expectedEvent, expectedMetrics, expectedUnits,
+ expectedDeviation, expectedScaling);
+
+ PMStatEntry actualDiff = statEntry.compare(statEntry2);
+
+ // test stat entry comparison
+ assertTrue(expectedDiff.equals(actualDiff));
+
+ }
+
+ public void testStatDataCollection() {
+ File statData = new File(STAT_RES + "perf_simple.stat");
+
+ //set up expected result
+ ArrayList<PMStatEntry> expectedStatList = new ArrayList<PMStatEntry>();
+
+ expectedStatList.add(new PMStatEntry((float) 4.78, "cpu-clock",
+ (float) 0.0, null, (float) 0.37, (float) 0.0));
+ expectedStatList.add(new PMStatEntry((float) 4.78, "task-clock",
+ (float) 0.08, "CPUs utilized", (float) 0.37, (float) 0.0));
+ expectedStatList.add(new PMStatEntry((float) 1164.0, "page-faults",
+ (float) 0.05, "M/sec", (float) 0.01, (float) 0.0));
+ expectedStatList.add(new PMStatEntry((float) 2164.0, "minor-faults",
+ (float) 0.06, "M/sec", (float) 0.01, (float) 0.0));
+ expectedStatList.add(new PMStatEntry((float) 9.6418E-4,
+ "seconds time elapsed", (float) 0.0, null, (float) 0.46,
+ (float) 0.0));
+
+ ArrayList<PMStatEntry> actualStatList = StatComparisonData.collectStats(statData);
+
+ assertFalse(actualStatList.isEmpty());
+
+ for(PMStatEntry expectedEntry : expectedStatList){
+ assertTrue(actualStatList.contains(expectedEntry));
+ }
+ }
+
+ public void testStatDataComparison() {
+ File oldStatData = new File(STAT_RES + "perf_old.stat");
+ File newStatData = new File(STAT_RES + "perf_new.stat");
+ StatComparisonData diffData = new StatComparisonData("title",
+ oldStatData, newStatData);
+
+ // expected comparison list
+ ArrayList<PMStatEntry> expectedDiff = new ArrayList<PMStatEntry>();
+
+ expectedDiff.add(new PMStatEntry((float) -4.0, "cpu-clock",
+ (float) 0.0, null, (float) 0.54, (float) 0.0));
+ expectedDiff.add(new PMStatEntry((float) -2000.0, "page-faults",
+ (float) -0.31, "M/sec", (float) 0.02, (float) 0.0));
+ expectedDiff.add(new PMStatEntry((float) 0.0, "context-switches",
+ (float) -0.13, "K/sec", (float) 36.34, (float) 0.0));
+ expectedDiff.add(new PMStatEntry((float) -1000.0, "minor-faults",
+ (float) -0.3, "M/sec", (float) 0.02, (float) 0.0));
+ expectedDiff.add(new PMStatEntry((float) 0.0, "major-faults",
+ (float) 0.0, "K/sec", (float) 0.0, (float) 0.0));
+ expectedDiff.add(new PMStatEntry((float) -0.008,
+ "seconds time elapsed", (float) 0.0, null, (float) 0.92,
+ (float) 0.0));
+
+ ArrayList<PMStatEntry> actualDiff = diffData.getComparisonStats();
+
+ assertFalse(actualDiff.isEmpty());
+
+ for (PMStatEntry expectedEntry : expectedDiff) {
+ assertTrue(actualDiff.contains(expectedEntry));
+ }
+ }
+
+ public void testStatComparisonResult() throws IOException {
+ File oldStatData = new File(STAT_RES + "perf_old.stat");
+ File newStatData = new File(STAT_RES + "perf_new.stat");
+ File diffStatData = new File(STAT_RES + "perf_diff.stat");
+
+ BufferedReader diffDataReader = new BufferedReader(new FileReader(
+ diffStatData));
+ StatComparisonData diffData = new StatComparisonData("title",
+ oldStatData, newStatData);
+
+ diffData.runComparison();
+ String actualResult = diffData.getResult();
+ String[] actulResultLines = actualResult.split("\n");
+
+ String curLine;
+ for (int i = 0; i < actulResultLines.length; i++) {
+ curLine = diffDataReader.readLine();
+ assertEquals(actulResultLines[i], curLine);
+ }
+
+ diffDataReader.close();
+ }
+}
diff --git a/perf/org.eclipse.linuxtools.perf/plugin.xml b/perf/org.eclipse.linuxtools.perf/plugin.xml
index 8fa310c..ec0d022 100644
--- a/perf/org.eclipse.linuxtools.perf/plugin.xml
+++ b/perf/org.eclipse.linuxtools.perf/plugin.xml
@@ -28,13 +28,21 @@
name="Perf Source Disassembly">
</view>
<view
- allowMultiple="true"
+ allowMultiple="false"
category="org.eclipse.linuxtools.profiling.ui"
class="org.eclipse.linuxtools.internal.perf.ui.StatView"
icon="icons/symbol.gif"
id="org.eclipse.linuxtools.perf.ui.StatView"
name="Perf Statistics">
</view>
+ <view
+ allowMultiple="true"
+ category="org.eclipse.linuxtools.profiling.ui"
+ class="org.eclipse.linuxtools.internal.perf.ui.StatComparisonView"
+ icon="icons/symbol.gif"
+ id="org.eclipse.linuxtools.perf.ui.StatViewDiff"
+ name="Perf Statistics Comparison">
+ </view>
</extension>
<extension
point="org.eclipse.help.contexts">
@@ -183,6 +191,12 @@
label="Save Statistics"
style="push">
</command>
+ <command
+ commandId="org.eclipse.linuxtools.perf.StatDiff"
+ id="org.eclipse.linuxtools.perf.StatDiff"
+ label="Compare Statistics"
+ style="push">
+ </command>
</menuContribution>
</extension>
<extension
@@ -197,5 +211,10 @@
id="org.eclipse.linuxtools.perf.SaveStatData"
name="Save Statistics">
</command>
+ <command
+ defaultHandler="org.eclipse.linuxtools.internal.perf.handlers.PerfStatsComparisonHandler"
+ id="org.eclipse.linuxtools.perf.StatDiff"
+ name="Compare Statistics">
+ </command>
</extension>
</plugin>
diff --git a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/PerfPlugin.java b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/PerfPlugin.java
index 1226c41..1645d06 100644
--- a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/PerfPlugin.java
+++ b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/PerfPlugin.java
@@ -14,12 +14,18 @@
*******************************************************************************/
package org.eclipse.linuxtools.internal.perf;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.List;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.linuxtools.internal.perf.model.TreeParent;
import org.eclipse.linuxtools.internal.perf.ui.PerfProfileView;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.plugin.AbstractUIPlugin;
@@ -37,6 +43,7 @@ public class PerfPlugin extends AbstractUIPlugin {
public static final String VIEW_ID = "org.eclipse.linuxtools.perf.ui.ProfileView";
public static final String SOURCE_DISASSEMBLY_VIEW_ID = "org.eclipse.linuxtools.perf.ui.SourceDisassemblyView";
public static final String STAT_VIEW_ID = "org.eclipse.linuxtools.perf.ui.StatView";
+ public static final String STAT_DIFF_VIEW_ID = "org.eclipse.linuxtools.perf.ui.StatViewDiff";
// Launch Config ID
public static final String LAUNCHCONF_ID = "org.eclipse.linuxtools.perf.launch.profile";
@@ -97,9 +104,6 @@ public class PerfPlugin extends AbstractUIPlugin {
public static final String PERF_DEFAULT_DATA = "perf.data";
public static final boolean DEBUG_ON = false; //Spew debug messages or not.
-
-
-
// The shared instance
private static PerfPlugin plugin;
@@ -122,6 +126,9 @@ public class PerfPlugin extends AbstractUIPlugin {
// Current working directory
private IPath curWorkingDir;
+ // Current stat comparison data
+ private StatComparisonData statDiffData;
+
public TreeParent getModelRoot() {
return _modelRoot;
}
@@ -138,6 +145,10 @@ public class PerfPlugin extends AbstractUIPlugin {
return curProfileData;
}
+ public StatComparisonData getStatDiffData() {
+ return statDiffData;
+ }
+
public IPath getWorkingDir(){
return curWorkingDir;
}
@@ -171,6 +182,10 @@ public class PerfPlugin extends AbstractUIPlugin {
this.curProfileData = perfProfileData;
}
+ public void setStatDiffData(StatComparisonData diffData){
+ this.statDiffData = diffData;
+ }
+
public void setWorkingDir(IPath workingDir){
curWorkingDir = workingDir;
}
@@ -235,4 +250,30 @@ public class PerfPlugin extends AbstractUIPlugin {
public static ImageDescriptor getImageDescriptor(String path) {
return imageDescriptorFromPlugin(PLUGIN_ID, path);
}
+
+ /**
+ * Log the given exception and display the message/reason in an error
+ * message box. (From org.eclipse.linuxtools.packagekit.ui.Activator)
+ *
+ * @param ex the given exception to display
+ * @since 2.0
+ */
+ public void openError(Exception ex, final String title) {
+ StringWriter writer = new StringWriter();
+ ex.printStackTrace(new PrintWriter(writer));
+
+ final String message = ex.getMessage();
+ final String formattedMessage = PLUGIN_ID + " : " + message; //$NON-NLS-1$
+ final Status status = new Status(IStatus.ERROR, PLUGIN_ID, formattedMessage, new Throwable(writer.toString()));
+
+ getLog().log(status);
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ ErrorDialog.openError(Display.getDefault().getActiveShell(),
+ title, message, status);
+ }
+ });
+ }
+
}
diff --git a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/StatComparisonData.java b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/StatComparisonData.java
new file mode 100644
index 0000000..91d0597
--- /dev/null
+++ b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/StatComparisonData.java
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat Inc.
+ * 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
+ *
+ * Contributors:
+ * Red Hat Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.perf;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.linuxtools.internal.perf.handlers.Messages;
+import org.eclipse.linuxtools.internal.perf.model.PMStatEntry;
+import org.eclipse.linuxtools.internal.perf.model.PMStatEntry.Type;
+
+/**
+ * Class containing all functionality for comparting perf statistics data.
+ */
+public class StatComparisonData {
+ // Old stats file.
+ private File oldFile;
+
+ // New stats file.
+ private File newFile;
+
+ // Comparison result string.
+ private String result = ""; //$NON-NLS-1$
+
+ // Title for this comparison run.
+ private String title;
+
+ public StatComparisonData(String title, File oldFile, File newFile) {
+ this.title = title;
+ this.oldFile = oldFile;
+ this.newFile = newFile;
+ }
+
+ public String getResult() {
+ return result;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * Compare stat data files and store the result in the result field.
+ */
+ public void runComparison() {
+ ArrayList<PMStatEntry> statsDiff = getComparisonStats();
+
+ if (!statsDiff.isEmpty()) {
+ String[][] statsDiffStr = new String[statsDiff.size()][];
+ int currentRow = 0;
+
+ // gather comparison results in a string array
+ for (PMStatEntry statEntry : statsDiff) {
+ statsDiffStr[currentRow] = statEntry.toStringArray();
+ currentRow++;
+ }
+
+ // apply format to each entry and set the result
+ String format = getFormat(statsDiffStr);
+ String curLine;
+ for (String[] statEntry : statsDiffStr) {
+ curLine = String.format(format, (Object[]) statEntry);
+ curLine = curLine.contains(PMStatEntry.TIME) ? "\n" + curLine //$NON-NLS-1$
+ : curLine;
+ result += curLine;
+ }
+ } else{
+
+ }
+ }
+
+ /**
+ * Return a PMStatEntry array with the result of the comparison between the
+ * old and new stat data files
+ * @return
+ */
+ public ArrayList<PMStatEntry> getComparisonStats() {
+ ArrayList<PMStatEntry> oldStats = collectStats(oldFile);
+ ArrayList<PMStatEntry> newStats = collectStats(newFile);
+ ArrayList<PMStatEntry> result = new ArrayList<PMStatEntry>();
+
+ for (PMStatEntry oldEntry : oldStats) {
+ for (PMStatEntry newEntry : newStats) {
+ if (oldEntry.equalEvents(newEntry)) {
+ result.add(oldEntry.compare(newEntry));
+ continue;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Collect statistics entries from the specified stat data file.
+ *
+ * @param file file to collect from
+ * @return List containing statistics entries from the given file.
+ */
+ public static ArrayList<PMStatEntry> collectStats(File statFile) {
+ ArrayList<PMStatEntry> result = new ArrayList<PMStatEntry>();
+ BufferedReader statReader = null;
+ try {
+ statReader = new BufferedReader(new FileReader(statFile));
+
+ // pattern for a valid perf stat entry
+ Pattern entryPattern = Pattern.compile(PMStatEntry.getString(Type.ENTRY_PATTERN));
+
+ // pattern for last stat entry (seconds elapsed):
+ Pattern totalTimePattern = Pattern.compile(PMStatEntry.getString(Type.TIME_PATTERN));
+
+ String line;
+ while((line = statReader.readLine()) != null ){
+ line = line.trim();
+ Matcher match = entryPattern.matcher(line);
+ String samples, event, usage, units, delta, scale;
+ PMStatEntry statEntry;
+
+ if(match.find()){
+
+ // extract information from groups
+ samples = match.group(1);
+ event = match.group(2);
+ usage = match.group(4);
+ units = match.group(5);
+ delta = match.group(7);
+ scale = match.group(11);
+
+ // create stat entry
+ statEntry = new PMStatEntry(toFloat(samples), event,
+ toFloat(usage), units, toFloat(delta),
+ toFloat(scale));
+
+ // add stat entry to results list
+ result.add(statEntry);
+
+ } else if(line.contains(PMStatEntry.TIME)){
+
+ // match seconds elapsed pattern
+ match = totalTimePattern.matcher(line);
+ if(match.find()){
+ samples = match.group(1);
+ event = match.group(2);
+ delta = match.group(4);
+
+ // create stat entry
+ statEntry = new PMStatEntry(toFloat(samples),
+ event, 0, null, toFloat(delta), 0);
+
+ result.add(statEntry);
+ }
+ }
+ }
+ return result;
+ } catch (FileNotFoundException e) {
+ PerfPlugin.getDefault().openError(e, Messages.MsgError);
+ } catch (IOException e) {
+ PerfPlugin.getDefault().openError(e, Messages.MsgError);
+ } finally {
+ try {
+ if (statReader != null) {
+ statReader.close();
+ }
+ } catch (IOException e) {
+ PerfPlugin.getDefault().openError(e, Messages.PerfResourceLeak_title);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Get formatting string from unformatted table.
+ *
+ * @param table array to construct formatting for.
+ * @return Formatting string representing the proper way to format the given
+ * table.
+ */
+ public String getFormat(String[][] table) {
+ // all entries have the same number of columns
+ int[] maxCharLen = new int[table[0].length];
+
+ // collect max number of characters per column
+ for (int i = 0; i < table.length; i++) {
+ for (int j = 0; j < table[i].length; j++) {
+ maxCharLen[j] = Math.max(maxCharLen[j], table[i][j].length());
+ }
+ }
+
+ // prepare format arguments
+ ArrayList<Integer> arguments = new ArrayList<Integer>();
+ for (int length : maxCharLen) {
+ arguments.add(length);
+ }
+
+ // generate format string
+ String entryFormat = String.format(
+ PMStatEntry.getString(Type.ENTRY_FORMAT),
+ arguments.toArray());
+
+ return entryFormat;
+ }
+
+ /**
+ * Get float representation of specified string.
+ *
+ * @param str String convert
+ * @return Float representation of string.
+ */
+ public static float toFloat(String str) {
+ try {
+ // remove commas from number string representation
+ return (str == null) ? 0
+ : Float.parseFloat(str.replace(",", "")); //$NON-NLS-1$//$NON-NLS-2$
+ } catch (NumberFormatException e) {
+ return 0;
+ }
+ }
+}
diff --git a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/AbstractComparisonHandler.java b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/AbstractComparisonHandler.java
new file mode 100644
index 0000000..2a7a28b
--- /dev/null
+++ b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/AbstractComparisonHandler.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc.
+ * 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
+ *
+ * Contributors:
+ * Camilo Bernal <cabernal@redhat.com> - Initial Implementation.
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.perf.handlers;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.IHandlerListener;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Abstract class providing functionality for comparison command handlers.
+ */
+public abstract class AbstractComparisonHandler implements IHandler {
+ // selected files
+ private static ArrayList<IFile> selectedFiles = new ArrayList<IFile>();
+
+ // previous selection
+ private ISelection prevSelection;
+
+ // workbench listener
+ private ISelectionListener workbenchListener;
+
+ @Override
+ public Object execute(ExecutionEvent event) {
+ MessageDialog.openInformation(Display.getCurrent().getActiveShell(),
+ Messages.MsgSelectionDiff, Messages.MsgSelectFiles);
+
+ // initialize workbench listener
+ workbenchListener = new ISelectionListener() {
+
+ @Override
+ public void selectionChanged(IWorkbenchPart sourcepart,
+ ISelection selection) {
+ handleSelection(sourcepart, selection);
+ }
+ };
+
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ IWorkbenchWindow workbenchWindow = workbench.getActiveWorkbenchWindow();
+ workbenchWindow.getSelectionService().addSelectionListener(
+ workbenchListener);
+ return null;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ // if the workbench listener is not null, then it's being used for the
+ // current comparison.
+ return workbenchListener == null;
+ }
+
+ @Override
+ public boolean isHandled() {
+ return isEnabled();
+ }
+
+ @Override
+ public void removeHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void addHandlerListener(IHandlerListener handlerListener) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void dispose() {
+ // TODO Auto-generated method stub
+ }
+
+ /**
+ * Get selected files.
+ *
+ * @return selected files
+ */
+ public static ArrayList<IFile> getSelectedFiles() {
+ return selectedFiles;
+ }
+
+ /**
+ * Get file from specified selection.
+ *
+ * @param selection the selection
+ * @return the selection's associated <code>IFile</code>
+ * @throws ClassCastException
+ */
+ private IFile getFile(ISelection selection) throws ClassCastException {
+ // Using IFiles in order to support remote files.
+ return (IFile) ((IStructuredSelection) selection).getFirstElement();
+ }
+
+ /**
+ * Validate specified file. If file is not valid it will not be added to
+ * list of selected files to compare. This method is to be implemented
+ * by extenders fof this class, the most common validation will be to
+ * check for file extension.
+ *
+ * @param file file to validate
+ * @return true if file is valid, false otherwise
+ */
+ protected abstract boolean isValidFile(IFile file);
+
+ /**
+ * Handle selected items.
+ *
+ * @param sourcepart the workbench part containing the selection
+ * @param selection current selection
+ */
+ private void handleSelection(IWorkbenchPart sourcepart, ISelection selection) {
+ if (!(selection.equals(prevSelection))) {
+ try {
+ IFile file = getFile(selection);
+
+ // check if selected files are set to be compared
+ if (isValidFile(file)
+ && selectedFiles.add(file)
+ && selectedFiles.size() == 2) {
+
+ /**
+ * as instructed to the user, first selected file is old
+ * data and second is the new data
+ */
+ IFile oldData = selectedFiles.get(0);
+ IFile newData = selectedFiles.get(1);
+
+ // confirm selections with user and trigger comparison
+ if (confirmSelections(oldData, newData)) {
+ handleComparison(oldData, newData);
+ }
+
+ clearSelections();
+ }
+ } catch (ClassCastException ex) {
+ // continue, there are other selections
+ }
+ }
+ prevSelection = selection;
+ }
+
+ /**
+ * Confirm selected files with user.
+ *
+ * @param oldFile old file to compare
+ * @param newFile new file to compare
+ * @return true if user confirms the selected files, false otherwise
+ */
+ private boolean confirmSelections(IFile oldFile, IFile newFile){
+ // confirmation message arguments
+ Object[] confirmMsgArgs = new String[] {
+ oldFile.getName(), newFile.getName() };
+
+ // confirmation message
+ String confirmMsg = MessageFormat.format(Messages.MsgConfirm_msg,
+ confirmMsgArgs);
+
+ // confirm selections with user
+ boolean confirm = MessageDialog.openConfirm(Display.getCurrent()
+ .getActiveShell(), Messages.MsgConfirm_title, confirmMsg);
+
+ return confirm;
+ }
+
+ /**
+ * Handle comparison of specified files.
+ *
+ * @param oldData old file to compare
+ * @param newData new file to compare
+ */
+ protected abstract void handleComparison(IFile oldData, IFile newData);
+
+ /**
+ * Clear selected files list and remove workbench listener.
+ */
+ private void clearSelections() {
+ PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+ .getSelectionService()
+ .removeSelectionListener(workbenchListener);
+ workbenchListener = null;
+ selectedFiles.clear();
+ }
+}
diff --git a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/Messages.java b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/Messages.java
index d60ead2..e5e6d23 100644
--- a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/Messages.java
+++ b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/Messages.java
@@ -26,6 +26,19 @@ public class Messages extends NLS {
public static String PerfSaveSession_failure_msg;
public static String PerfResourceLeak_title;
public static String PerfResourceLeak_msg;
+
+ public static String MsgClearSelection;
+ public static String MsgSelectionDiff;
+ public static String MsgSelectFiles;
+ public static String MsgError;
+ public static String MsgError_0;
+ public static String MsgError_1;
+ public static String MsgError_2;
+ public static String MsgWarning_0;
+ public static String MsgWarning_1;
+ public static String MsgConfirm_title;
+ public static String MsgConfirm_msg;
+ public static String ContentDescription_0;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/PerfSaveSessionHandler.java b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/PerfSaveSessionHandler.java
index 29a43e6..d0ae9c5 100644
--- a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/PerfSaveSessionHandler.java
+++ b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/PerfSaveSessionHandler.java
@@ -24,7 +24,8 @@ import org.eclipse.linuxtools.internal.perf.PerfPlugin;
* Handler for saving a perf profile session.
*/
public class PerfSaveSessionHandler extends AbstractSaveDataHandler {
- private static String DATA_EXT = "data"; //$NON-NLS-1$
+
+ public static final String DATA_EXT = "data"; //$NON-NLS-1$
@Override
public File saveData(String filename) {
diff --git a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/PerfStatsComparisonHandler.java b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/PerfStatsComparisonHandler.java
new file mode 100644
index 0000000..3099763
--- /dev/null
+++ b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/PerfStatsComparisonHandler.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc.
+ * 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
+ *
+ * Contributors:
+ * Camilo Bernal <cabernal@redhat.com> - Initial Implementation.
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.perf.handlers;
+
+import java.io.File;
+import java.text.MessageFormat;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.linuxtools.internal.perf.PerfPlugin;
+import org.eclipse.linuxtools.internal.perf.StatComparisonData;
+import org.eclipse.linuxtools.internal.perf.ui.StatComparisonView;
+
+/**
+ * Command handler for comparins perf statistics files.
+ */
+public class PerfStatsComparisonHandler extends AbstractComparisonHandler {
+
+ @Override
+ protected boolean isValidFile(IFile file) {
+ return file == null ? false : PerfSaveStatsHandler.DATA_EXT.equals(file
+ .getFileExtension());
+ }
+
+ @Override
+ protected void handleComparison(IFile oldData, IFile newData) {
+ String title = MessageFormat.format(Messages.ContentDescription_0,
+ new Object[] { oldData.getName(), newData.getName() });
+
+ // get corresponding files
+ File oldDatum = oldData.getLocation().toFile();
+ File newDatum = newData.getLocation().toFile();
+
+ // create comparison data and run comparison.
+ StatComparisonData diffData = new StatComparisonData(title, oldDatum, newDatum);
+ diffData.runComparison();
+
+ PerfPlugin.getDefault().setStatDiffData(diffData);
+ StatComparisonView.refreshView();
+ }
+
+}
diff --git a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/messages.properties b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/messages.properties
index 5e18869..fb11ab4 100644
--- a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/messages.properties
+++ b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/handlers/messages.properties
@@ -9,4 +9,17 @@ PerfSaveSession_failure_msg= Could not save profiling session to {0}
PerfSaveStat_error_title=Error Saving Statistics
PerfSaveStat_error_msg=Could not save statistics to {0}
PerfResourceLeak_title=Resource Leak
-PerfResourceLeak_msg=Could not close {0} \ No newline at end of file
+PerfResourceLeak_msg=Could not close {0}
+
+MsgClearSelection=Clear Selections
+MsgSelectionDiff=Compare Sessions
+MsgSelectFiles=Please select the older and newer perf statistics files you wish to compare.
+MsgError=Error
+MsgError_0= Error", "Selections are not proper perf statistics files.
+MsgError_1= Selections are not proper perf statistics files.
+MsgError_2=Current selection is invalid.
+MsgWarning_0=Warning
+MsgWarning_1=Please select two perf statistics files.
+MsgConfirm_title=Confirm Selections
+MsgConfirm_msg=Old Session: {0} \nNew Session: {1}
+ContentDescription_0=Sessions compared: {0} , {1} \ No newline at end of file
diff --git a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/model/PMStatEntry.java b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/model/PMStatEntry.java
new file mode 100644
index 0000000..1a50b23
--- /dev/null
+++ b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/model/PMStatEntry.java
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, Inc.
+ * 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
+ *
+ * Contributors:
+ * Camilo Bernal <cabernal@redhat.com> - Initial Implementation.
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.perf.model;
+
+/**
+ * Representation of a single entry in a perf stat report.
+ */
+public class PMStatEntry {
+ // Samples of current event.
+ private float samples;
+
+ // Current event.
+ private String event;
+
+ // Metrics for current event.
+ private float metrics;
+
+ // Metrics' units.
+ private String units;
+
+ // Standard deviation of stats.
+ private float deviation;
+
+ // Scaling.
+ private float scaling;
+
+ // Types of relevant strings for a perf stat entry.
+ public static enum Type {
+ ENTRY_PATTERN, TIME_PATTERN, ENTRY_FORMAT, PERCENT_FORMAT, METRIC_FORMAT
+ }
+
+ // Reg-ex strings for elements in a perf stat entry.
+ public static final String DECIMAL = "\\d+[\\.\\,\\d]*"; //$NON-NLS-1$
+ public static final String PERCENTAGE = "(\\d+(\\.\\d+)?)\\%"; //$NON-NLS-1$
+ public static final String SAMPLES = "(" + DECIMAL + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ public static final String EVENT = "(\\w+[\\-\\w]+)"; //$NON-NLS-1$
+ public static final String METRICS = "(" + DECIMAL + ")"; //$NON-NLS-1$//$NON-NLS-2$
+ public static final String UNITS = "([a-zA-Z\\/\\s\\%]*)"; //$NON-NLS-1$
+ public static final String DELTA = "(\\(\\s\\+\\-\\s*" + PERCENTAGE + "\\s\\))"; //$NON-NLS-1$ //$NON-NLS-2$
+ public static final String SCALE = "(\\[\\s*" + PERCENTAGE + "\\])"; //$NON-NLS-1$ //$NON-NLS-2$
+ public static final String TIME_UNIT = "(seconds\\stime\\selapsed)"; //$NON-NLS-1$
+ public static final String TIME = "seconds time elapsed"; //$NON-NLS-1$
+
+ public PMStatEntry(float samples, String event, float metrics,
+ String units, float deviation, float scaling) {
+ this.samples = samples;
+ this.event = event;
+ this.metrics = metrics;
+ this.units = units;
+ this.deviation = deviation;
+ this.scaling = scaling;
+ }
+
+ public float getSamples() {
+ return samples;
+ }
+
+ public String getEvent() {
+ return (event == null) ? "" : event; //$NON-NLS-1$
+ }
+
+
+ public float getMetrics() {
+ return metrics;
+ }
+
+ public String getUnits() {
+ return (units == null) ? "" : units.trim(); //$NON-NLS-1$
+ }
+
+ public float getDeviation() {
+ return deviation;
+ }
+
+
+ public float getScaling() {
+ return scaling;
+ }
+
+ public String getFormattedMetrics(){
+ return String.format("%.3f", metrics); //$NON-NLS-1$
+ }
+
+ public String getFormattedDeviation(){
+ return String.format("%.2f%%", deviation); //$NON-NLS-1$
+ }
+
+ @Override
+ public boolean equals(Object entry) {
+ PMStatEntry statEntry = (PMStatEntry) entry;
+ if (statEntry == null
+ || samples != statEntry.getSamples()
+ || metrics != statEntry.getMetrics()
+ || deviation != statEntry.getDeviation()
+ || scaling != statEntry.getScaling()) {
+ return false;
+ }
+
+ if (!getEvent().equals(statEntry.getEvent())
+ || !getUnits().equals(statEntry.getUnits())) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if PMStatEntry refer to the same event.
+ * @param entry PMStatEntry to check against
+ * @return true if events are equals, false otherwise.
+ */
+ public boolean equalEvents(PMStatEntry entry) {
+ String event = entry.getEvent();
+ if (this.event != null && event != null) {
+ return this.event.equals(event);
+ }
+ return false;
+ }
+
+ /**
+ * Auto-generated hashCode method.
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Float.floatToIntBits(deviation);
+ result = prime * result + ((event == null) ? 0 : event.hashCode());
+ result = prime * result + Float.floatToIntBits(metrics);
+ result = prime * result + Float.floatToIntBits(samples);
+ result = prime * result + Float.floatToIntBits(scaling);
+ result = prime * result + ((units == null) ? 0 : units.hashCode());
+ return result;
+ }
+
+ /**
+ * Compare this PMStatEntry with the specified one, and return an object
+ * with the result.
+ *
+ * @param entry PMStatEntry to compare against
+ * @return a PMStatEntry representing the resulting comparison.
+ */
+ public PMStatEntry compare(PMStatEntry entry){
+ float occurrenceDiff = entry.getSamples() - this.samples;
+ float metricsDiff = entry.getMetrics() - this.metrics;
+ float deviationDiff = entry.getDeviation() + this.deviation;
+ float scalingDiff = entry.getScaling() + this.scaling;
+
+ return new PMStatEntry(occurrenceDiff, event, metricsDiff, units, deviationDiff, scalingDiff);
+ }
+
+ /**
+ * Return formatted String values of fields in a string array.
+ *
+ * @return String[] String array containing string value of fields.
+ */
+ public String[] toStringArray(){
+ return new String[] { String.valueOf(samples),
+ getEvent(),
+ getFormattedMetrics(),
+ getUnits(),
+ getFormattedDeviation()};
+ }
+
+ /**
+ * Get string related to specified type of perf stat entry:
+ * <p>
+ * ENTRY_PATTERN: - Regex for a generic entry.</br>
+ * TIME_PATTERN: - Regex for total time entry.</br>
+ * ENTRY_FORMAT: - Format string for a generic entry.
+ * </p>
+ *
+ * @param type
+ * @return
+ */
+ public static String getString(Type type) {
+ String stringRes = ""; //$NON-NLS-1$
+ switch (type) {
+ case ENTRY_PATTERN:
+ // samples, event, metrics, units, deviation, scaling
+ stringRes = "^" + SAMPLES; //$NON-NLS-1$
+ stringRes += "\\s" + EVENT; //$NON-NLS-1$
+ stringRes += "\\s*(\\#\\s+" + METRICS + UNITS + ")?"; //$NON-NLS-1$ //$NON-NLS-2$
+ stringRes += DELTA + "?"; //$NON-NLS-1$
+ stringRes += "(\\s" + SCALE + ")?$"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ return stringRes;
+ case TIME_PATTERN:
+ // samples, time elapsed, deviation
+ stringRes += "^" + SAMPLES; //$NON-NLS-1$
+ stringRes += "\\s" + TIME_UNIT; //$NON-NLS-1$
+ stringRes += "\\s+" + DELTA; //$NON-NLS-1$
+
+ return stringRes;
+ case ENTRY_FORMAT:
+ // Stat entry format
+ stringRes += " %%1$%1$1ds "; //$NON-NLS-1$
+ stringRes += "%%2$-%2$1ds # "; //$NON-NLS-1$
+ stringRes += "%%3$%3$1ds "; //$NON-NLS-1$
+ stringRes += "%%4$-%4$1ds "; //$NON-NLS-1$
+ stringRes += "( +- %%5$%5$1ds )\n"; //$NON-NLS-1$
+
+ return stringRes;
+ default:
+ return stringRes;
+ }
+ }
+
+}
diff --git a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/ui/StatComparisonView.java b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/ui/StatComparisonView.java
new file mode 100644
index 0000000..c55e3ae
--- /dev/null
+++ b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/ui/StatComparisonView.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat Inc.
+ * 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
+ *
+ * Contributors:
+ * Red Hat Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.perf.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.linuxtools.internal.perf.PerfPlugin;
+import org.eclipse.linuxtools.internal.perf.StatComparisonData;
+import org.eclipse.linuxtools.internal.perf.model.PMStatEntry;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * Perf Statistics Comparison view
+ */
+public class StatComparisonView extends ViewPart {
+
+ // color values constasts
+ private static final Color RED = new Color(Display.getDefault(), 150, 0, 0);
+ private static final Color GREEN = new Color(Display.getDefault(), 0, 100, 0);
+
+ // event occurrence reg-ex
+ private static String OCCURRENCE = "\\s*(\\-?+" //$NON-NLS-1$
+ + PMStatEntry.DECIMAL + ").*"; //$NON-NLS-1$
+
+ private StyledText text;
+ private static int SECONDARY_ID = 0;
+
+ public StatComparisonView() {
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ parent.setLayoutData(new GridLayout(1, true));
+
+ text = new StyledText(parent, SWT.WRAP | SWT.V_SCROLL);
+ text.setEditable(false);
+
+ StatComparisonData statsDiff = PerfPlugin.getDefault()
+ .getStatDiffData();
+ if (statsDiff != null) {
+ setStyledText(statsDiff.getResult());
+ setContentDescription(statsDiff.getTitle());
+ }
+ }
+
+ @Override
+ public void setFocus() {
+ return;
+ }
+
+ /**
+ * Set String input in text display. Adapted from
+ * org.eclipse.linuxtools.internal.perf.ui.SourceDisassemblyView.
+ *
+ * @param input text to display
+ */
+ private void setStyledText(String input) {
+ text.setText(input);
+ text.setAlignment(SWT.LEFT);
+ List<StyleRange> styles = new ArrayList<StyleRange>();
+ int ptr = 0;
+
+ // set default TextConsole font (monospaced).
+ text.setFont(JFaceResources.getFont(JFaceResources.TEXT_FONT));
+
+ String[] lines = input.split("\n");
+
+ for(String line : lines){
+ if (Pattern.matches(OCCURRENCE, line)) {
+ Matcher m = Pattern.compile(OCCURRENCE).matcher(line);
+ if (m.matches() && m.group(1) != null) {
+ try {
+ float occurrence = StatComparisonData.toFloat(m
+ .group(1).trim());
+ if (occurrence > 0) {
+ styles.add(new StyleRange(ptr, line.length(), RED,
+ null));
+ } else if (occurrence < 0) {
+ styles.add(new StyleRange(ptr, line.length(),
+ GREEN, null));
+ }
+ } catch (NumberFormatException e) {
+ // set no StyleRange
+ }
+ }
+ }
+ // + 1 to skip over the '\n' at EOL that the tokenizer eats
+ ptr += line.length() + 1;
+ }
+
+ text.setStyleRanges(styles.toArray(new StyleRange[0]));
+ }
+
+ /**
+ * Show new view with provided input.
+ */
+ public static void refreshView() {
+ Display.getDefault().syncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ PlatformUI
+ .getWorkbench()
+ .getActiveWorkbenchWindow()
+ .getActivePage()
+ .showView(PerfPlugin.STAT_DIFF_VIEW_ID,
+ Integer.toString(SECONDARY_ID++),
+ IWorkbenchPage.VIEW_CREATE);
+ } catch (PartInitException e) {
+ IStatus status = new Status(IStatus.ERROR,
+ PerfPlugin.PLUGIN_ID, e.getMessage(), e);
+ PerfPlugin.getDefault().getLog().log(status);
+ }
+ }
+ });
+ }
+}
diff --git a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/ui/StatView.java b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/ui/StatView.java
index 20300c3..3fb368e 100644
--- a/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/ui/StatView.java
+++ b/perf/org.eclipse.linuxtools.perf/src/org/eclipse/linuxtools/internal/perf/ui/StatView.java
@@ -20,7 +20,6 @@ import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
-import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
@@ -31,7 +30,6 @@ import org.eclipse.ui.part.ViewPart;
public class StatView extends ViewPart {
private StyledText text;
- private static int SECONDARY_ID = 0;
public StatView() {
}
@@ -61,7 +59,20 @@ public class StatView extends ViewPart {
// the default TextConsole font (we want monospaced)
text.setFont(JFaceResources.getFont(JFaceResources.TEXT_FONT));
}
+ /**
+ * Update to most recent statistics data.
+ */
+ public void updateData(){
+ StatData data = PerfPlugin.getDefault().getStatData();
+ if (data != null) {
+ setStyledText(data.getPerfData());
+ setContentDescription(data.getTitle());
+ }
+ }
+ /**
+ * Refresh perf statistics view.
+ */
public static void refreshView () {
Display.getDefault().syncExec(new Runnable() {
@@ -69,10 +80,9 @@ public class StatView extends ViewPart {
public void run() {
try {
// A new view is created every time
- PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
- .showView(PerfPlugin.STAT_VIEW_ID,
- Integer.toString(SECONDARY_ID++),
- IWorkbenchPage.VIEW_CREATE);
+ StatView view = (StatView) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
+ .showView(PerfPlugin.STAT_VIEW_ID);
+ view.updateData();
} catch (PartInitException e) {
IStatus status = new Status(IStatus.ERROR, PerfPlugin.PLUGIN_ID, e.getMessage(), e);
PerfPlugin.getDefault().getLog().log(status);