Bug 324687 -  Consolidate 3.7 and 4.1 builds
diff --git a/bundles/org.eclipse.build.tools/.classpath b/bundles/org.eclipse.build.tools/.classpath
index 49c14c9..2115495 100644
--- a/bundles/org.eclipse.build.tools/.classpath
+++ b/bundles/org.eclipse.build.tools/.classpath
@@ -5,7 +5,7 @@
 	<classpathentry kind="src" path="src_bugzilla"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-	<classpathentry kind="var" path="ECLIPSE_HOME/plugins/org.eclipse.osgi.util_3.2.100.v20100503.jar"/>
+	<classpathentry kind="var" path="ECLIPSE_HOME/plugins/org.eclipse.osgi_3.7.0.v20100910.jar"/>
 	<classpathentry kind="var" path="ECLIPSE_HOME/plugins/org.apache.ant_1.7.1.v20090120-1145/lib/ant.jar"/>
 	<classpathentry kind="var" path="ECLIPSE_HOME/plugins/org.apache.ant_1.7.1.v20090120-1145/lib/ant-launcher.jar"/>
 	<classpathentry kind="output" path="bin"/>
diff --git a/bundles/org.eclipse.build.tools/buildTools.jar b/bundles/org.eclipse.build.tools/buildTools.jar
index 1f753eb..1972dc3 100644
--- a/bundles/org.eclipse.build.tools/buildTools.jar
+++ b/bundles/org.eclipse.build.tools/buildTools.jar
Binary files differ
diff --git a/bundles/org.eclipse.build.tools/src/org/eclipse/releng/generators/TestResultsGenerator.java b/bundles/org.eclipse.build.tools/src/org/eclipse/releng/generators/TestResultsGenerator.java
index a0b261d..bf17dfb 100644
--- a/bundles/org.eclipse.build.tools/src/org/eclipse/releng/generators/TestResultsGenerator.java
+++ b/bundles/org.eclipse.build.tools/src/org/eclipse/releng/generators/TestResultsGenerator.java
@@ -132,13 +132,10 @@
 	private int counter = 0;
 	//The four configurations, add new configurations to test results here + update
 	//testResults.php.template for changes
-	private String[] testsConfig = {"linux.gtk.x86.xml",
-			"linux.gtk.x86_6.0.xml",
-			"macosx.cocoa.x86_5.0.xml",
-			"win32.win32.x86.xml",
+	private String[] testsConfig = {"linux.gtk.x86_6.0.xml",
+			"macosx.cocoa.x86_5.0.xml",		
 			"win32.win32.x86_6.0.xml"};
 
-
 	public static void main(String[] args) {
 		TestResultsGenerator test = new TestResultsGenerator();
 		test.setDropTokenList(
diff --git a/bundles/org.eclipse.test.performance.ui/html/builds-comparison.html b/bundles/org.eclipse.test.performance.ui/html/builds-comparison.html
new file mode 100644
index 0000000..3bded21
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/html/builds-comparison.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+	<title>Builds Comparison view</title>
+</head>
+
+<body>
+<h1>Builds Comparison view</h1>
+<p>
+This view shows the scenarios status table of the difference between two builds
+selected in the <a href="builds.html">Builds view</a>.
+</p><p>
+The comparison between the two builds is shown for each component in a
+separated tab which contains a table made of all scenarios (lines) and all
+configuration (columns).<br>
+<i>Note that this format is similar than the one used to generate performance
+results HTML pages...</i>
+</p>
+
+<h2>Filters</h2>
+<p>
+
+<h3>Scenarios filter</h3>
+<ul>
+<li>Advanced scenarios: hide the scenarios which are not in the fingerprints</li>
+</ul>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.test.performance.ui/html/builds.html b/bundles/org.eclipse.test.performance.ui/html/builds.html
index e0dcf60..8e71a63 100644
--- a/bundles/org.eclipse.test.performance.ui/html/builds.html
+++ b/bundles/org.eclipse.test.performance.ui/html/builds.html
@@ -64,6 +64,24 @@
 eclipsebuildserv or fullmoon...</i>
 </p>
 
+<h2><a name="writecomparison">Write comparison</h2>
+<p>
+From this view, it is also possible to write the comparison between two 
+selected builds using the <b>Write comparison</b> item of the View menu:
+</p>
+<p><img src="images/write-comparison-menu.png" alt="Write comparison menu item"/></p>
+<p>
+The written HTML file will contain the Scenario Status Table as it would
+have been generated but comparing the two selected build instead of comparing
+a build vs a baseline.
+</p><p>
+This is helpful to see if a regression occurs after having made a change with 
+possible impact performance...
+</p>
+<p>Note that this comparison can also be shown in the
+<a href="builds-comparison.html">Builds Comparison view</a>...
+</p>
+
 <h2>Filters</h2>
 <p>
 There are several possible filters in this view.
diff --git a/bundles/org.eclipse.test.performance.ui/html/components.html b/bundles/org.eclipse.test.performance.ui/html/components.html
index be5b75d..6c9b714 100644
--- a/bundles/org.eclipse.test.performance.ui/html/components.html
+++ b/bundles/org.eclipse.test.performance.ui/html/components.html
@@ -47,7 +47,8 @@
 The red cross means that there's at least one scenario on one machine for
 the last build with a failure (i.e. a regression over 10%).
 </p><p>
-The warning icon means that some warnings occur for some results. The current possible warning are:
+The warning icon means that some warnings occur for some results.
+The current possible warning are:
 <ul>
 <li>error over the 3% threshold on test(s)</li>
 <li>unreliable test(s): the deviation through the test(s) history is over 20%</li>
@@ -88,5 +89,22 @@
 by default in this view. Currently the survey only concerns the fingerprints
 scenario, hence the corresponding filter is also activated by default.
 </p>
+
+<h2><a name="writestatus">Write status</h2>
+<p>
+From this view, it is also possible to write the status file for the last
+active build (see <a href="preferences.html#lastbuild">Last build</a>) by
+using the <b>Write status</b> item of the View menu:
+</p>
+<p><img src="images/write-status-menu.png" alt="Write status menu item"/></p>
+<p>
+The written status file will contain all scenarios which have failures,
+except those excluded by the status preferences set in the preferences page
+(see <a href="preferences.html#status">Status</a>)
+</p><p>
+Then it's easy to see the new regression occurring in a build when comparing
+to the previous build status file:
+</p>
+<p><img src="images/write-status-comparison.png" alt="Compare write status files"/></p>
 </body>
 </html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.test.performance.ui/html/images/preferences-database.png b/bundles/org.eclipse.test.performance.ui/html/images/preferences-database.png
new file mode 100644
index 0000000..3cbceb4
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/html/images/preferences-database.png
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/html/images/preferences-default-dim.png b/bundles/org.eclipse.test.performance.ui/html/images/preferences-default-dim.png
new file mode 100644
index 0000000..cbc02d6
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/html/images/preferences-default-dim.png
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/html/images/preferences-eclipse-versions.png b/bundles/org.eclipse.test.performance.ui/html/images/preferences-eclipse-versions.png
new file mode 100644
index 0000000..2771215
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/html/images/preferences-eclipse-versions.png
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/html/images/preferences-lastbuild.png b/bundles/org.eclipse.test.performance.ui/html/images/preferences-lastbuild.png
new file mode 100644
index 0000000..26d85c0
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/html/images/preferences-lastbuild.png
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/html/images/preferences-milestones.png b/bundles/org.eclipse.test.performance.ui/html/images/preferences-milestones.png
new file mode 100644
index 0000000..7f666af
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/html/images/preferences-milestones.png
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/html/images/preferences-results-dim.png b/bundles/org.eclipse.test.performance.ui/html/images/preferences-results-dim.png
new file mode 100644
index 0000000..dbb6726
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/html/images/preferences-results-dim.png
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/html/images/preferences-status.png b/bundles/org.eclipse.test.performance.ui/html/images/preferences-status.png
new file mode 100644
index 0000000..6aa53dd
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/html/images/preferences-status.png
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/html/images/write-comparison-menu.png b/bundles/org.eclipse.test.performance.ui/html/images/write-comparison-menu.png
new file mode 100644
index 0000000..d34b368
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/html/images/write-comparison-menu.png
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/html/images/write-status-comparison.png b/bundles/org.eclipse.test.performance.ui/html/images/write-status-comparison.png
new file mode 100644
index 0000000..51cc333
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/html/images/write-status-comparison.png
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/html/images/write-status-menu.png b/bundles/org.eclipse.test.performance.ui/html/images/write-status-menu.png
new file mode 100644
index 0000000..41bb7fa
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/html/images/write-status-menu.png
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/html/overview.html b/bundles/org.eclipse.test.performance.ui/html/overview.html
index 45001b0..5b22fea 100644
--- a/bundles/org.eclipse.test.performance.ui/html/overview.html
+++ b/bundles/org.eclipse.test.performance.ui/html/overview.html
@@ -9,8 +9,8 @@
 <body>
 <h1>Overview</h1>
 The performance results tool provide an easy way to look at results collected
-while running performance tests on a build. It is accessible using the <b>Performance Results</b>
-perspective:
+while running performance tests on a build. It is accessible using the
+<b>Performance Results</b> perspective:
 <p><img src="images/perspective.png" alt="Performance Results perspective"/></p>
 <p>
 There are 4 views in this perspective:
@@ -26,12 +26,13 @@
 </ul>
 </p><p>
 The goal of this tool is both to look at performance results database numbers
-and to verify whether a build result may have scenario showing performance regression.
+and to verify whether a build result have scenarios showing performance regression.
 </p><p>
-The view to use to look at performance results number is the <a href="components.html">Components view</a>.
-In this results are displayed in a hierarchical tree which have a similar structure
-than the generated HTML pages (e.g.
-<a href="http://download.eclipse.org/eclipse/downloads/drops/R-3.5-200906111540/performance/performance.php">Eclipse 3.5.0</a>).
+The view to use to look at performance results number is the
+<a href="components.html">Components view</a>. In this view, results are
+displayed in a hierarchical tree which have a similar structure than
+the generated HTML pages (e.g.
+<a href="http://download.eclipse.org/eclipse/downloads/drops/R-3.6-201006080911/performance/performance.php">Eclipse 3.6.0</a>).
 The complete performance results information is provided on each element of the tree in the
 <a href="properties.html">Properties view</a>. This is typically useful when a scenario
 results looks weird to have the ability to verify that the numbers looks correct
diff --git a/bundles/org.eclipse.test.performance.ui/html/preferences.html b/bundles/org.eclipse.test.performance.ui/html/preferences.html
index 61c6858..000be5d 100644
--- a/bundles/org.eclipse.test.performance.ui/html/preferences.html
+++ b/bundles/org.eclipse.test.performance.ui/html/preferences.html
@@ -11,21 +11,84 @@
 <p>
 The tool have some preferences which may be configured by advanced users.
 This must be done carefully otherwise, either no data could be read by the tool
-and/or generated results could be puzzled.
+and/or generatead results could be puzzled.
 </p><p>
-Here's what the page looks like:
-<p><img src="images/preferences.png" alt="Preferences"/></p>
 
-<h2>Database</h2>
+<h3><a name="eclipse_version">Eclipse version</h3>
+<p><img src="images/preferences-eclipse-versions.png" alt="Preferences Eclipse versions"/></p>
+<p>
+The Eclipse version on which the performance results belongs to. There are
+only two possible choice: the maintenance and the current versions.
+</p>
+
+<h3><a name="database">Database</h3>
+<p><img src="images/preferences-database.png" alt="Preferences Database"/></p>
 <p>
 By default the tool does not connect to any performance results database as common
 users might not have enough rights to access it. However, users having these
 rights may want to look at the database contents and update the local data files
 with it. Hence, it is possible to configure the tool to connect to a database
-which may be either local or on the releng server (<code><b>trelenggtk</b></code>).
+which may be either local or on the releng server (<code><b>minsky</b></code>).
+</p><p>
+Note that the folder for the local database must be the parent of the
+<code>perfDb3x</code> folder otherwise you'll get an error message.
 </p>
 
-<h2>Milestones</h2>
+<h3><a name="status">Status</h3>
+<p><img src="images/preferences-status.png" alt="Preferences Status"/></p>
+<p>
+The status preferences can be set to exclude some tests while written
+the status file (see <a href="components.html#writestatus">Write status</a>).
+</p><p>
+Flying over each check-box or radio buttons gives a short explanation of each
+preference value
+</p><p>
+Here are the detailed explanation of these status preferences:
+<ul>
+<li><b>Values</b>: Check-box to include the values of the failing tests in the
+status file. Note that is not recommended to do so when status want to be
+compared between builds</li>
+<li><b>Error level</b>: Level of the error from which the test result is
+excluded from the file:
+<ul>
+<li>None: the test is always included in the status file whatever the error
+level is</li>
+<li>Invalid: the test is not included when the error level is over 100%</li>
+<li>Weird: the test is not included when the error level is over 50%</li>
+<li>Suspicious: the test is not included when the error level is over 25%</li>
+<li>Noticeable: the test is not included when the error level is over 3%</li>
+</ul>
+</li>
+<li><b>Small value</b>: The test is not included when a small value is detected:
+<ul>
+<li>Build value: the test is not included when the value for this build test value
+is below than 100ms (<i>as the test duration is below the recommended minimum
+value it's not necessary to strongly survey it...</i>)</li>
+<li>Delta value: the test is not included when the value of the difference between
+the build and the baseline is below than 100ms (<i>as the regression is below
+what a normal user can detect, it may not be necessary to report it...</i>)</li>
+</ul>
+</li>
+<li><b>Statistics</b>: Level of deviation of test history since the first build
+from which the test result is not included in the status file:
+<ul>
+<li>None: the test is always included in the status file whatever the deviation
+is</li>
+<li>Unstable: the test is not included when the deviation is over 10%</li>
+<li>Erratic: the test is not included when the error level is over 20%</li>
+</ul>
+</li>
+<li><b>Builds to confirm</b>: The number of builds to confirm a regression.
+As tests may have <i>natural</i> variation, it's often necessary to have several
+builds to confirm that a regression really occurs. This preference allow to
+define how many consecutive builds must show a regression before including
+a test result in the status file...
+</li>
+</ul>
+</p>
+
+<h3><a name="milestones">Milestones</h3>
+<p><img src="images/preferences-milestones.png" alt="Preferences Milestones"/></p>
 <p>
 These are the list of the version milestones. Each milestone is a date string
 using the <b>yyyymmddHHMM</b> format. When a new milestone is shipped, then a new
@@ -33,7 +96,20 @@
 list and emphasize it...
 </p>
 
-<h2>Default dimension</h2>
+<h3><a name="lastbuild">Last build</h3>
+<p><img src="images/preferences-lastbuild.png" alt="Preferences Last build"/></p>
+<p>
+The last build on which verifications and/or generation want to be done. When
+not set (which is the default value) the last build of the database is taken
+into account.
+</p><p>
+All builds after the selected one are ignored by the tool likewise they would
+have no local data. Changing this value will trigger the initialization of
+the local data which will be read again.
+</p>
+
+<h2><a name="defaultdim">Default dimension</h2>
+<p><img src="images/preferences-default-dim.png" alt="Preferences Default dimension"/></p>
 <p>
 This is the dimension used to compute delta and make the verification. Currently
 this is the <b>Elapsed Process Time</b> dimension.
@@ -43,7 +119,8 @@
 added to the list...</i>
 </p>
 
-<h2>Results dimensions</h2>
+<h2><a name="resultsdim">Results dimensions</h2>
+<p><img src="images/preferences-results-dim.png" alt="Preferences Results dimension"/></p>
 <p>
 These are dimensions displayed in the scenario data HTML pages. Currently there
 are the <b>Elapsed Process Time</b> and the <b>CPU Time</b>. Having these dimensions
diff --git a/bundles/org.eclipse.test.performance.ui/icons/compare_view.gif b/bundles/org.eclipse.test.performance.ui/icons/compare_view.gif
new file mode 100644
index 0000000..dc549bc
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/icons/compare_view.gif
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/performanceui.jar b/bundles/org.eclipse.test.performance.ui/performanceui.jar
index 59053ea..ab92fef 100644
--- a/bundles/org.eclipse.test.performance.ui/performanceui.jar
+++ b/bundles/org.eclipse.test.performance.ui/performanceui.jar
Binary files differ
diff --git a/bundles/org.eclipse.test.performance.ui/plugin.xml b/bundles/org.eclipse.test.performance.ui/plugin.xml
index 491cb79..04d80d3 100644
--- a/bundles/org.eclipse.test.performance.ui/plugin.xml
+++ b/bundles/org.eclipse.test.performance.ui/plugin.xml
@@ -49,6 +49,14 @@
             name="Component Results"
             restorable="true">
       </view>
+      <view
+            category="Performances"
+            class="org.eclipse.test.internal.performance.results.ui.BuildsComparisonView"
+            icon="icons/compare_view.gif"
+            id="org.eclipse.test.internal.performance.results.ui.BuildsComparisonView"
+            name="Builds comparison"
+            restorable="true">
+      </view>
    </extension>
    <extension
          point="org.eclipse.core.runtime.preferences">
diff --git a/bundles/org.eclipse.test.performance.ui/readme.html b/bundles/org.eclipse.test.performance.ui/readme.html
index e72c2ac..f4cb0cc 100644
--- a/bundles/org.eclipse.test.performance.ui/readme.html
+++ b/bundles/org.eclipse.test.performance.ui/readme.html
@@ -41,12 +41,12 @@
 (HEAD should be fine).</li><li>Create a Cloudscape or derby plug-in as described 
 <A HREF="http://dev.eclipse.org/viewcvs/index.cgi/*checkout*/org.eclipse.test.performance/doc/Performance%20Tests%20HowTo.html?rev=HEAD&content-type=text/html#cloudscape">here</A>.</li><li>Set 
 the environment variable &quot;dbloc&quot; to the location of the database containing 
-the performance data<br> For example:<br> <ul> <li> export dbloc=net://trelenggtk.ottawa.ibm.com 
-(Linux)</li><li>set dbloc==net://trelenggtk.ottawa.ibm.com (Windows)<br> </li></ul></li></ul><p><b>Running 
+the performance data<br> For example:<br> <ul> <li> export dbloc=net://minsky.ottawa.ibm.com 
+(Linux)</li><li>set dbloc==net://minsky.ottawa.ibm.com (Windows)<br> </li></ul></li></ul><p><b>Running 
 the program</b></p><p>From a terminal or dos prompt,<br> </p><OL><LI>Set the environment 
 variable &quot;dbloc&quot; to the location of the database containing the performance 
-data<BR> For example:<UL><LI>export dbloc=net://trelenggtk.ottawa.ibm.com (Linux)</LI><LI>set 
-dbloc==net://trelenggtk.ottawa.ibm.com (Windows)<BR><BR></LI></UL></LI><LI>cd 
+data<BR> For example:<UL><LI>export dbloc=net://minsky.ottawa.ibm.com (Linux)</LI><LI>set 
+dbloc==net://minsky.ottawa.ibm.com (Windows)<BR><BR></LI></UL></LI><LI>cd 
 to org.eclipse.releng.basebuilder\plugins\org.eclipse.test.performance.ui\scripts<BR></LI><LI>If 
 running on Linux, execute &quot;chmod 755 genresults&quot;</LI><LI>Execute the 
 following command:<b><br> <br> genresults -baseline &lt;baseline build id&gt; 
diff --git a/bundles/org.eclipse.test.performance.ui/scripts/genresults b/bundles/org.eclipse.test.performance.ui/scripts/genresults
index abe595d..8dfb7de 100644
--- a/bundles/org.eclipse.test.performance.ui/scripts/genresults
+++ b/bundles/org.eclipse.test.performance.ui/scripts/genresults
@@ -1,6 +1,6 @@
 # !/bin/sh
 
-#export dbloc=net://trelenggtk.ottawa.ibm.com
+#export dbloc=net://minsky.ottawa.ibm.com
 #required when running on Linux Motif
 export LD_LIBRARY_PATH=./../../..
 
diff --git a/bundles/org.eclipse.test.performance.ui/scripts/genresults.bat b/bundles/org.eclipse.test.performance.ui/scripts/genresults.bat
index a4dc454..fcc1b37 100644
--- a/bundles/org.eclipse.test.performance.ui/scripts/genresults.bat
+++ b/bundles/org.eclipse.test.performance.ui/scripts/genresults.bat
@@ -1,6 +1,6 @@
 @echo off
 
-REM set dbloc=net://trelenggtk.ottawa.ibm.com
+REM set dbloc=net://minsky.ottawa.ibm.com
 
 java -Declipse.perf.dbloc=%dbloc% -jar .\..\..\..\plugins\org.eclipse.equinox.launcher.jar -application org.eclipse.test.performance.ui.resultGenerator %*
 
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/BuildResults.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/BuildResults.java
index bde02ff..21e3021 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/BuildResults.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/BuildResults.java
@@ -204,7 +204,8 @@
  * @return The value of the standard deviation
  */
 public double getDeviation(int dim_id) {
-	return this.stddev[getDimIndex(dim_id)];
+	final int dimIndex = getDimIndex(dim_id);
+	return dimIndex < 0 ? 0 : this.stddev[dimIndex];
 }
 
 /**
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/ConfigResults.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/ConfigResults.java
index 275555d..46225a0 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/ConfigResults.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/ConfigResults.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
  * 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
@@ -239,7 +239,7 @@
  * 		<li>{@link AbstractResults#BASELINE_ERROR_INDEX}: the error made while measuring the baseline value</li>
  * 	</ul>
  */
-double[] getNumbers(BuildResults buildResults, BuildResults baselineResults) {
+public double[] getNumbers(BuildResults buildResults, BuildResults baselineResults) {
 	if (baselineResults == null) {
 		return null;
 	}
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/DB_Results.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/DB_Results.java
index b96f17a..dc02f78 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/DB_Results.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/DB_Results.java
@@ -657,7 +657,7 @@
 	String lastBaselineBuild = null;
 	for (int i=0; i<BUILDS_LENGTH; i++) {
 		String build = BUILDS[i];
-		if (build.startsWith(DB_BASELINE_PREFIX)) {
+		if (build.startsWith(DB_VERSION_REF)) {
 			String buildDate = build.substring(build.indexOf('_')+1);
 			if (buildDate.compareTo(date) < 0) {
 				if (lastBaselineBuild == null || build.compareTo(lastBaselineBuild) > 0) {
@@ -666,7 +666,7 @@
 			}
 		}
 	}
-	if (lastBaselineBuild == null) {
+	if (lastBaselineBuild == null && BUILDS.length > 0) {
 		return BUILDS[0];
 	}
 	return lastBaselineBuild;
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/PerformanceResults.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/PerformanceResults.java
index 7cebe7e..74bcb21 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/PerformanceResults.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/PerformanceResults.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
  * 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
@@ -670,7 +670,7 @@
 		}
 		int idx = n-1;
 		String lastBuild = this.allBuildNames[idx--];
-		while (lastBuild.startsWith(DB_Results.getDbBaselinePrefix())) {
+		while (idx > 0 && lastBuild.startsWith(DB_Results.getDbBaselinePrefix())) {
 			lastBuild = this.allBuildNames[idx--];
 		}
 		this.needToUpdateLocalFile = this.name == null || Util.getBuildDate(lastBuild).compareTo(Util.getBuildDate(this.name)) > 0;
@@ -719,6 +719,16 @@
  */
 public void setBaselineName(String buildName) {
 	this.baselineName = buildName;
+	if (this.baselinePrefix == null || !this.baselineName.startsWith(this.baselinePrefix)) {
+		// Usually hat baseline name format is *always* x.y_yyyyMMddhhmm_yyyyMMddhhmm
+		int index = this.baselineName.lastIndexOf('_');
+		if (index > 0) {
+			this.baselinePrefix = this.baselineName.substring(0, index);
+		} else {
+//				this.baselinePrefix = DB_Results.getDbBaselinePrefix();
+			this.baselinePrefix = this.baselineName;
+		}
+	}
 }
 
 private void setDefaults() {
@@ -737,7 +747,8 @@
 			this.name = DB_Results.getLastCurrentBuild();
 			if (this.dbRequired) {
 				if (this.name == null) {
-					throw new RuntimeException("Cannot find any current build!"); //$NON-NLS-1$
+//					throw new RuntimeException("Cannot find any current build!"); //$NON-NLS-1$
+					this.name = "No current build!";
 				}
 				this.allBuildNames = DB_Results.getBuilds();
 				this.components = DB_Results.getComponents();
@@ -762,13 +773,16 @@
 	}
 
 	// Init baseline prefix if not set
-	if (this.baselinePrefix == null && this.baselineName != null) {
-		// Assume that baseline name format is *always* x.y_yyyyMMddhhmm_yyyyMMddhhmm
-		int index = this.baselineName.lastIndexOf('_');
-		if (index > 0) {
-			this.baselinePrefix = this.baselineName.substring(0, index);
-		} else {
-			this.baselinePrefix = DB_Results.getDbBaselinePrefix();
+	if (this.baselineName != null) {
+		if (this.baselinePrefix == null || !this.baselineName.startsWith(this.baselinePrefix)) {
+			// Usually hat baseline name format is *always* x.y_yyyyMMddhhmm_yyyyMMddhhmm
+			int index = this.baselineName.lastIndexOf('_');
+			if (index > 0) {
+				this.baselinePrefix = this.baselineName.substring(0, index);
+			} else {
+//				this.baselinePrefix = DB_Results.getDbBaselinePrefix();
+				this.baselinePrefix = this.baselineName;
+			}
 		}
 	}
 
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/BuildResultsElement.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/BuildResultsElement.java
index 82c1766..4fb226d 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/BuildResultsElement.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/BuildResultsElement.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
  * 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
@@ -162,7 +162,7 @@
 	return null;
 }
 
-private BuildResults getBuildResults() {
+BuildResults getBuildResults() {
 	return (BuildResults) this.results;
 }
 
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ComponentResultsElement.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ComponentResultsElement.java
index c8b21f3..d72c0f4 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ComponentResultsElement.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ComponentResultsElement.java
@@ -201,12 +201,12 @@
 	}
 }
 
-StringBuffer writableStatus(StringBuffer buffer, int kind, StringBuffer excluded) {
+StringBuffer getFailures(StringBuffer buffer, int kind, StringBuffer excluded) {
 	// Write status for scenarios having error
 	if ((getStatus() & ERROR_MASK) != 0) {
 
 		// Get children status
-		StringBuffer childrenBuffer = super.writableStatus(new StringBuffer(), kind, excluded);
+		StringBuffer childrenBuffer = super.getFailures(new StringBuffer(), kind, excluded);
 
 		// Write status on file if not excluded
 		if (childrenBuffer.length() > 0) {
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ConfigResultsElement.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ConfigResultsElement.java
index a00ed03..e6d199b 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ConfigResultsElement.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ConfigResultsElement.java
@@ -277,7 +277,7 @@
 /*
  * Write the element status in the given stream
  */
-StringBuffer writableStatus(StringBuffer buffer, int kind, StringBuffer excluded) {
+StringBuffer getFailures(StringBuffer buffer, int kind, StringBuffer excluded) {
 	if ((this.status & BIG_DELTA) != 0) { // there's a failure on this config
 
 		// Get numbers
@@ -298,7 +298,7 @@
 			}
 			int confirmed = 1;
 			for (int i=1; i<numbersLength; i++) {
-				if (numbers[i][AbstractResults.DELTA_VALUE_INDEX] < -0.1) {
+				if (numbers[i] != null && numbers[i][AbstractResults.DELTA_VALUE_INDEX] < -0.1) {
 					confirmed++;
 				}
 			}
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/PerformanceResultsElement.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/PerformanceResultsElement.java
index a7073a5..467bb86 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/PerformanceResultsElement.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/PerformanceResultsElement.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
  * 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
@@ -16,11 +16,14 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.PrintStream;
 import java.util.Arrays;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.test.internal.performance.results.db.*;
+import org.eclipse.test.internal.performance.results.ui.BuildsComparisonTable;
 import org.eclipse.test.internal.performance.results.utils.IPerformancesConstants;
 import org.eclipse.test.internal.performance.results.utils.Util;
+import org.eclipse.test.performance.ui.Utils;
 
 public class PerformanceResultsElement extends ResultsElement {
 
@@ -58,7 +61,7 @@
 	return baselines;
 }
 
-String[] getBuildNames() {
+public String[] getBuildNames() {
 	if (this.buildNames == null) {
 		this.buildNames = DB_Results.DB_CONNECTION
 			? DB_Results.getBuilds()
@@ -210,7 +213,7 @@
 /*
  * Write the component status in the given file
  */
-public StringBuffer writeStatus(File resultsFile, int kind) {
+public StringBuffer writeFailures(File resultsFile, int kind) {
 	if (this.results == null) {
 		return null;
 	}
@@ -308,7 +311,7 @@
 				buffer.append(Util.LINE_SEPARATOR);
 			}
 			stream.write(buffer.toString().getBytes());
-			StringBuffer componentBuffer = writableStatus(new StringBuffer(), kind, excluded);
+			StringBuffer componentBuffer = getFailures(new StringBuffer(), kind, excluded);
 			if (componentBuffer.length() > 0) {
 				stream.write(componentBuffer.toString().getBytes());
 			}
@@ -324,4 +327,53 @@
 	return excluded;
 }
 
+/*
+ * Write the comparison between two builds in the given file
+ */
+public void writeComparison(File resultsFile, String build, String reference) {
+	if (this.results == null) {
+		return;
+	}
+	try {
+		// Create the stream
+		PrintStream stream = new PrintStream(new BufferedOutputStream(new FileOutputStream(resultsFile)));
+
+		// Print main title
+		stream.print("<link href=\""+Utils.TOOLTIP_STYLE+"\" rel=\"stylesheet\" type=\"text/css\">\n");
+		stream.print("<script src=\""+Utils.TOOLTIP_SCRIPT+"\"></script>\n");
+		stream.print("<script src=\""+Utils.FINGERPRINT_SCRIPT+"\"></script>\n");
+		stream.print(Utils.HTML_DEFAULT_CSS);
+		stream.print("<body>");
+		stream.print("<h2>Performance comparison of ");
+		stream.print(build);
+		stream.print(" relative to ");
+		int index = reference.indexOf('_');
+		if (index > 0) {
+			stream.print(reference.substring(0, index));
+			stream.print(" (");
+			index = reference.lastIndexOf('_');
+			stream.print(reference.substring(index+1, reference.length()));
+			stream.print(')');
+		} else {
+			stream.print(reference);
+		}
+		stream.print("</h2>\n");
+
+		// Print a comparison table for each component
+		try {
+			int length = this.children.length;
+			for (int i=0; i<length; i++) {
+				BuildsComparisonTable table = new BuildsComparisonTable(this.children[i].getName(), stream, build, reference);
+				table.print(getPerformanceResults());
+			}
+		}
+		finally {
+			stream.print("</body>");
+			stream.close();
+		}
+	} catch (FileNotFoundException e) {
+		System.err.println("Can't create output file"+resultsFile); //$NON-NLS-1$
+	}
+}
+
 }
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ResultsElement.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ResultsElement.java
index b3646d3..ecd5aac 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ResultsElement.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ResultsElement.java
@@ -585,12 +585,12 @@
 }
 
 /*
- * Write the element status in the given stream
+ * Write the failures of the element in the given buffer
  */
-StringBuffer writableStatus(StringBuffer buffer, int kind, StringBuffer excluded) {
-	int length = this.children.length;
+StringBuffer getFailures(StringBuffer buffer, int kind, StringBuffer excluded) {
+	int length = getChildren().length;
 	for (int i=0; i<length; i++) {
-		this.children[i].writableStatus(buffer, kind, excluded);
+		this.children[i].getFailures(buffer, kind, excluded);
 	}
 	return buffer;
 }
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ScenarioResultsElement.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ScenarioResultsElement.java
index 5957d6a..40daddd 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ScenarioResultsElement.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/model/ScenarioResultsElement.java
@@ -126,12 +126,12 @@
 	}
 }
 
-StringBuffer writableStatus(StringBuffer buffer, int kind, StringBuffer excluded) {
+StringBuffer getFailures(StringBuffer buffer, int kind, StringBuffer excluded) {
 	// Write status for scenarios having error
 	if ((getStatus() & ERROR_MASK) != 0) {
 
 		// Get children status
-		StringBuffer childrenBuffer = super.writableStatus(new StringBuffer(), kind, excluded);
+		StringBuffer childrenBuffer = super.getFailures(new StringBuffer(), kind, excluded);
 
 		// Write status on file if not excluded
 		if (childrenBuffer.length() > 0) {
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsComparisonTab.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsComparisonTab.java
new file mode 100644
index 0000000..5615b23
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsComparisonTab.java
@@ -0,0 +1,539 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.test.internal.performance.results.ui;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.ToolTip;
+import org.eclipse.test.internal.performance.results.db.AbstractResults;
+import org.eclipse.test.internal.performance.results.db.BuildResults;
+import org.eclipse.test.internal.performance.results.db.ConfigResults;
+import org.eclipse.test.internal.performance.results.db.PerformanceResults;
+import org.eclipse.test.internal.performance.results.db.ScenarioResults;
+import org.eclipse.test.internal.performance.results.model.BuildResultsElement;
+import org.eclipse.test.internal.performance.results.model.PerformanceResultsElement;
+import org.eclipse.test.internal.performance.results.model.ResultsElement;
+import org.eclipse.test.internal.performance.results.utils.IPerformancesConstants;
+import org.eclipse.test.internal.performance.results.utils.Util;
+
+
+/**
+ * Tab to display all performances results numbers for a configuration (i.e a performance machine).
+ */
+public class BuildsComparisonTab {
+
+	// Colors
+	static final Display DEFAULT_DISPLAY = Display.getDefault();
+	static final Color BLUE= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_BLUE);
+	static final Color DARK_GREEN= DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_DARK_GREEN);
+	static final Color GRAY = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_GRAY);
+	static final Color MAGENTA = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_MAGENTA);
+	static final Color RED = DEFAULT_DISPLAY.getSystemColor(SWT.COLOR_RED);
+
+	// SWT resources
+	Shell shell;
+	Display display;
+	Table table;
+	private GC gc;
+	private Color lightred;
+	private Color lightyellow;
+	private Color darkyellow;
+	private Color blueref;
+	private Font boldFont;
+	private Font italicFont;
+	private Font boldItalicFont;
+	Map toolTips;
+
+	// Information
+	String componentName;
+	double[][] allValues;
+	double[][] allErrors;
+
+	// Cells management
+	Point tableOrigin, tableSize;
+	int columnsCount, rowsCount;
+	List firstLine;
+
+	// Eclipse preferences
+	private IEclipsePreferences preferences;
+
+/*
+ * Default constructor.
+ */
+public BuildsComparisonTab(String name) {
+    this.componentName = name;
+	this.preferences = new InstanceScope().getNode(IPerformancesConstants.PLUGIN_ID);
+}
+
+/**
+ * Creates the tab folder page.
+ *
+ * @param view The view on which to create the tab folder page
+ * @return the new page for the tab folder
+ */
+Composite createTabFolderPage (BuildsComparisonView view) {
+	// Cache the shell and display.
+	this.shell = view.tabFolder.getShell();
+	this.display = this.shell.getDisplay();
+
+	// Remove old table if present
+	boolean initResources = this.table == null;
+	if (this.table != null) {
+		disposeTable();
+	}
+
+	// Create the "children" table
+	int style = SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION;
+	this.table = new Table(view.tabFolder, style);
+	this.table.setLinesVisible (true);
+	this.table.setHeaderVisible (true);
+	GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
+	gridData.heightHint = 150;
+	this.table.setLayoutData (gridData);
+	this.gc = new GC(this.table);
+
+	// Init resources
+	if (initResources) initResources();
+
+	// Add columns to the table
+	TableColumn firstColumn = new TableColumn(this.table, SWT.CENTER);
+	firstColumn.setText("");
+	PerformanceResultsElement results = view.getResults();
+	String [] configDescriptions = results.getConfigDescriptions();
+	int length = configDescriptions.length;
+	for (int i = 0; i < length; i++) {
+		TableColumn column = new TableColumn(this.table, SWT.CENTER);
+		column.setText(configDescriptions[i]);
+	}
+
+	// Add lines to the table
+	this.toolTips = new HashMap();
+	boolean fingerprints = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS);
+	fillTable(results, view.currentBuild, view.referenceBuild, fingerprints);
+
+	// Updated columns
+	for (int i=0; i<=length; i++) {
+		TableColumn column = this.table.getColumn(i);
+		column.setWidth(i==0?120:100);
+	}
+
+	// Store table info
+	this.columnsCount = length;
+
+	// Listen to mouse track events to display the table cell corresponding tooltip.
+	MouseTrackListener mouseTrackListener = new MouseTrackListener() {
+		ToolTip currentTooltip;
+		public void mouseHover(MouseEvent e) {
+			if (this.currentTooltip != null) {
+				this.currentTooltip.setVisible(false);
+				this.currentTooltip = null;
+			}
+			Point cellPosition = currentCellPosition(e.x, e.y);
+			if (cellPosition != null) {
+				ToolTip tooltip = (ToolTip) BuildsComparisonTab.this.toolTips.get(cellPosition);
+				if (tooltip != null) {
+					Point location = BuildsComparisonTab.this.table.toDisplay(new Point(e.x, e.y));
+					tooltip.setLocation(location);
+					tooltip.setVisible(true);
+					this.currentTooltip = tooltip;
+				}
+			}
+		}
+		public void mouseEnter(MouseEvent e) {
+		}
+		public void mouseExit(MouseEvent e) {
+		}
+	};
+	this.table.addMouseTrackListener(mouseTrackListener);
+
+	// Select the first line by default (as this is the current build)
+	this.table.select(0);
+
+	// Return the built composite
+	return this.table;
+}
+
+/*
+ * Create and store a tooltip with the given information and at the given position.
+ */
+void createToolTip(String toolTipText, String toolTipMessage, int toolTipStyle, Point position) {
+	ToolTip toolTip = new ToolTip(this.table.getShell(), toolTipStyle);
+	toolTip.setAutoHide(true);
+	toolTip.setText(toolTipText);
+	toolTip.setMessage(/*"("+col+","+row+") "+*/toolTipMessage);
+	this.toolTips.put(position, toolTip);
+}
+
+/*
+ * Get the current cell position (column, row) from a point position.
+ */
+Point currentCellPosition(int x, int y) {
+
+	// Compute the origin of the visible area
+	if (this.tableOrigin == null) {
+		this.tableOrigin = new Point(0, this.table.getHeaderHeight());
+	}
+
+	// Increment width until over current y position
+	int height= this.tableOrigin.y;
+	int row = this.table.getTopIndex();
+	while (row<this.rowsCount && height<y) {
+		height += this.table.getItemHeight();
+		row++;
+	}
+	if (height < y) {
+		// return when position is over the last line
+		return null;
+	}
+	row--;
+
+	// Increment width until being over current x position
+	int col = 0;
+	TableItem tableItem = this.table.getItem(row);
+	Rectangle bounds = tableItem.getBounds(col);
+	while (col<this.columnsCount) {
+		int max = bounds.x + bounds.width + this.table.getGridLineWidth();
+		if (x <= max) break;
+		if (col == this.columnsCount) {
+			// return when position is over the last column
+			return null;
+		}
+		col++;
+		bounds = tableItem.getBounds(col);
+	}
+
+	// Return the found table cell position
+	return new Point(col, row);
+}
+
+/*
+ * Dispose all SWT resources.
+ */
+public void dispose() {
+	if (this.boldFont != null) {
+		this.boldFont.dispose();
+	}
+	if (this.italicFont != null) {
+		this.italicFont.dispose();
+	}
+	if (this.boldItalicFont != null) {
+		this.boldItalicFont.dispose();
+	}
+	if (this.darkyellow != null) {
+		this.darkyellow.dispose();
+	}
+	if (this.lightyellow != null) {
+		this.lightyellow.dispose();
+	}
+	if (this.lightred != null) {
+		this.lightred.dispose();
+	}
+	if (this.blueref != null) {
+		this.blueref.dispose();
+	}
+	disposeTable();
+}
+
+/*
+ * Dispose all SWT controls associated with the table.
+ */
+private void disposeTable() {
+	if (this.toolTips != null) {
+		Iterator cells = this.toolTips.keySet().iterator();
+		while (cells.hasNext()) {
+			ToolTip toolTip = (ToolTip) this.toolTips.get(cells.next());
+			toolTip.dispose();
+		}
+	}
+	this.table.dispose();
+	this.tableOrigin = null;
+	this.firstLine = null;
+}
+
+/*
+ * Fill the lines of the tables.
+ * Get all the information from the model which are returned in a list (lines) of lists (columns).
+ */
+private void fillTable(PerformanceResultsElement results, String currentBuild, String referenceBuild, boolean fingerprints) {
+
+	// Get all the scenario for the component
+	final PerformanceResults performanceResults = results.getPerformanceResults();
+	List scenarios = performanceResults.getComponentScenarios(this.componentName);
+	int size = scenarios.size();
+
+	// Get thresholds
+	int failurePref = this.preferences.getInt(IPerformancesConstants.PRE_COMPARISON_THRESHOLD_FAILURE, IPerformancesConstants.DEFAULT_COMPARISON_THRESHOLD_FAILURE);
+	int errorPref = this.preferences.getInt(IPerformancesConstants.PRE_COMPARISON_THRESHOLD_ERROR, IPerformancesConstants.DEFAULT_COMPARISON_THRESHOLD_ERROR);
+	int improvementPref = this.preferences.getInt(IPerformancesConstants.PRE_COMPARISON_THRESHOLD_IMPROVEMENT, IPerformancesConstants.DEFAULT_COMPARISON_THRESHOLD_IMPROVEMENT);
+	final double failureThreshold = -failurePref / 100.0;
+	final double errorThreshold = errorPref / 100.0;
+	final double improvementThreshold = improvementPref / 100.0;
+
+	// Build the map made of one line per scenario results
+	final String[] configs = performanceResults.getConfigNames(true/*sort*/);
+	for (int i=0; i<size; i++) {
+		ScenarioResults scenarioResults = (ScenarioResults) scenarios.get(i);
+		if (!scenarioResults.isValid()) continue;
+		final boolean fingerprint = scenarioResults.hasSummary();
+		if (!fingerprints || fingerprint) {
+
+			// The first column is the scenario name
+			String scenarioName = scenarioResults.getShortName();
+			TableItem item = new TableItem (this.table, SWT.NONE);
+			item.setText(scenarioName);
+
+			// Bold font and blue ref background color if this is a fingerprint test
+			Font italic;
+			if (fingerprint) {
+				item.setFont(0, this.boldFont);
+				item.setBackground(this.blueref);
+				italic = this.boldItalicFont;
+			} else {
+				italic = this.italicFont;
+			}
+
+			// Fill config columns
+			int length = configs.length;
+			for (int j=0; j<length; j++) {
+
+				// See whether there's available numbers
+				int col = j+1;
+				final ConfigResults configResults = scenarioResults.getConfigResults(configs[j]);
+				if (configResults == null || !configResults.isValid()) {
+					item.setText(col, "Invalid");
+					item.setForeground(col, GRAY);
+					item.setFont(col, italic);
+					continue;
+				}
+				final BuildResults buildResults = configResults.getBuildResults(currentBuild);
+				if (buildResults == null) {
+					item.setText(col, "Missing results");
+					item.setForeground(col, GRAY);
+					item.setFont(col, italic);
+					continue;
+				}
+				final BuildResults referenceResults = configResults.getBuildResults(referenceBuild);
+				if (referenceResults == null) {
+					item.setText(col, "Missing ref");
+					item.setForeground(col, GRAY);
+					item.setFont(col, italic);
+					continue;
+				}
+
+				// Get numbers and infos
+				double[] values = configResults.getNumbers(buildResults, referenceResults);
+
+				// Reset tooltip info
+				String toolTipText = null;
+				String toolTipMessage = null;
+				int toolTipStyle = SWT.BALLOON;
+
+				// Get values array
+				final double buildValue = values[AbstractResults.BUILD_VALUE_INDEX];
+				final double referenceValue = values[AbstractResults.BASELINE_VALUE_INDEX];
+				final double delta = values[AbstractResults.DELTA_VALUE_INDEX];
+				final double error = values[AbstractResults.DELTA_ERROR_INDEX];
+
+				// Set text with delta value
+				final StringBuffer address = new StringBuffer("http://fullmoon.ottawa.ibm.com/downloads/drops/");
+				address.append(currentBuild);
+				address.append("/performance/");
+				address.append(configResults.getName());
+				address.append('/');
+				address.append(scenarioResults.getFileName());
+				address.append(".html");
+				StringBuffer buffer = new StringBuffer("<a href=\"");
+				buffer.append(address);
+				buffer.append("\">");
+				final String itemText = Util.PERCENTAGE_FORMAT.format(delta);
+				buffer.append(itemText);
+				buffer.append("</a>");
+
+				// Simple text
+				item.setText(col, itemText);
+
+				/* Link + Editor
+				Link link = new Link(this.table, SWT.CENTER);
+				link.setText(buffer.toString());
+				link.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {
+						Program.launch(address.toString());
+					}
+				});
+				final TableEditor editor = new TableEditor(this.table);
+				editor.grabHorizontal = editor.grabVertical = true;
+				editor.verticalAlignment = SWT.CENTER;
+				editor.horizontalAlignment = SWT.CENTER;
+				editor.setEditor(link, item, col);
+				*/
+
+				// Compute the tooltip to display on the cell
+				if (error > errorThreshold) {
+					// error is over the threshold
+					item.setForeground(col, this.darkyellow);
+					toolTipText = "May be not reliable";
+					toolTipMessage = "The error on this result is "+Util.PERCENTAGE_FORMAT.format(error)+", hence it may be not reliable";
+					toolTipStyle |= SWT.ICON_WARNING;
+				}
+				if (delta < -0.1) {
+					// delta < -10%: failure shown by an red-cross icon + text in red
+					item.setImage(col, ResultsElement.ERROR_IMAGE);
+				}
+				if (delta < failureThreshold) {
+					// negative delta over the threshold shown in red
+					item.setForeground(col, RED);
+				} else if (delta > improvementThreshold) {
+					// positive delta over the threshold are shown in green
+					item.setForeground(col, DARK_GREEN);
+				}
+
+				// Moderate the status if the build value or the difference is small
+				if (buildValue < 100 || referenceValue < 100) {
+					if (toolTipText == null) {
+						toolTipText = "";
+					} else {
+						toolTipText += ", ";
+					}
+					toolTipText += "Small value";
+					if (toolTipMessage == null) {
+						toolTipMessage = "";
+					} else {
+						toolTipMessage += ".\n";
+					}
+					toolTipMessage += "This test has a small value ("+buildValue+"ms)";
+					toolTipStyle |= SWT.ICON_WARNING;
+					item.setImage(col, ResultsElement.WARN_IMAGE);
+				}
+
+				// Add information in tooltip when history shows big variation
+				double deviation = configResults.getStatistics(Util.BASELINE_BUILD_PREFIXES)[3];
+				if (deviation > 0.2) {
+					// deviation is over 20% over the entire history
+					if (toolTipText == null) {
+						toolTipText = "";
+					} else {
+						toolTipText += ", ";
+					}
+					toolTipText += "History shows erratic values";
+					if (toolTipMessage == null) {
+						toolTipMessage = "";
+					} else {
+						toolTipMessage += ".\n";
+					}
+					toolTipMessage += "The results history shows that the variation of its delta is over 20% ("+Util.PERCENTAGE_FORMAT.format(deviation)+"), hence its result is surely not reliable";
+					// set the text in italic
+					item.setFont(col, italic);
+					toolTipStyle |= SWT.ICON_INFORMATION;
+				} else if (deviation > 0.1) { // moderate the status when the test
+					// deviation is between 10% and 20% over the entire history
+					if (toolTipText == null) {
+						toolTipText = "";
+					} else {
+						toolTipText += ", ";
+					}
+					toolTipText += "History shows unstable values";
+					if (toolTipMessage == null) {
+						toolTipMessage = "";
+					} else {
+						toolTipMessage += ".\n";
+					}
+					toolTipMessage += "The results history shows that the variation of its delta is between 10% and 20% ("+Util.PERCENTAGE_FORMAT.format(deviation)+"), hence its result may not be really reliable";
+					// set the text in italic
+					item.setFont(col, italic);
+					if (toolTipStyle == SWT.BALLOON && delta >= -0.1) {
+						toolTipStyle |= SWT.ICON_INFORMATION;
+					} else {
+						// reduce icon severity from error to warning
+						toolTipStyle |= SWT.ICON_WARNING;
+					}
+				}
+
+				// Set tooltip
+				if (toolTipText != null) {
+					createToolTip(toolTipText, toolTipMessage, toolTipStyle, new Point(col, i));
+				}
+			}
+		}
+	}
+	this.rowsCount = size;
+}
+
+protected Shell getShell() {
+	return this.shell;
+}
+
+/*
+ * The tab text is the full machine name.
+ */
+public String getTabText() {
+	return Util.componentDisplayName(this.componentName);
+}
+
+/*
+ * Init the SWT resources
+ */
+private void initResources() {
+	// Fonts
+	String fontDataName = this.gc.getFont().getFontData()[0].toString();
+	FontData fdItalic = new FontData(fontDataName);
+	fdItalic.setStyle(SWT.ITALIC);
+	this.italicFont = new Font(this.display, fdItalic);
+	FontData fdBold = new FontData(fontDataName);
+	fdBold.setStyle(SWT.BOLD);
+	this.boldFont = new Font(this.display, fdBold);
+	FontData fdBoldItalic = new FontData(fontDataName);
+	fdBoldItalic.setStyle(SWT.BOLD | SWT.ITALIC);
+	this.boldItalicFont = new Font(this.display, fdBoldItalic);
+
+	// Colors
+	this.lightred = new Color(DEFAULT_DISPLAY, 220, 50, 50);
+	this.lightyellow = new Color(DEFAULT_DISPLAY, 255, 255, 160);
+	this.darkyellow = new Color(DEFAULT_DISPLAY, 160, 160, 0);
+	this.blueref = new Color(DEFAULT_DISPLAY, 200, 200, 255);
+}
+
+/*
+ * Select the line corresponding to the given build.
+ */
+void select(BuildResultsElement buildResultsElement) {
+	int count = this.table.getItemCount();
+	String buildName = buildResultsElement.getName();
+	TableItem[] items = this.table.getItems();
+	for (int i=0; i<count; i++) {
+		if (items[i].getText().endsWith(buildName)) {
+			this.table.deselect(this.table.getSelectionIndex());
+			this.table.select(i);
+			return;
+		}
+	}
+}
+}
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsComparisonTable.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsComparisonTable.java
new file mode 100644
index 0000000..440c052
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsComparisonTable.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.test.internal.performance.results.ui;
+
+import java.io.PrintStream;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.eclipse.test.internal.performance.results.db.AbstractResults;
+import org.eclipse.test.internal.performance.results.db.BuildResults;
+import org.eclipse.test.internal.performance.results.db.ConfigResults;
+import org.eclipse.test.internal.performance.results.db.PerformanceResults;
+import org.eclipse.test.internal.performance.results.db.ScenarioResults;
+import org.eclipse.test.performance.ui.Utils;
+
+/**
+ * This class is responsible to print html table with the difference between two
+ * builds for all the scenarios and the configuration of a specific component.
+ */
+public class BuildsComparisonTable {
+
+	private static final double DEFAULT_FAILURE_THRESHOLD = PerformanceResults.DEFAULT_FAILURE_THRESHOLD / 100.0 / 2;
+	private String component;
+	private PrintStream stream;
+	String buildName, referenceName;
+
+public BuildsComparisonTable(String name, PrintStream stream, String build, String reference) {
+    this.component = name;
+    this.stream = stream;
+    this.buildName = build;
+    this.referenceName = reference;
+}
+
+/**
+ * Prints the HTML representation of scenario status table into the given stream.
+ */
+public void print(PerformanceResults performanceResults) {
+
+	List scenarios = performanceResults.getComponentScenarios(this.component);
+	int size = scenarios.size();
+
+	// Print titles
+	printTitle();
+	this.stream.print("<table border=\"1\">\n");
+	this.stream.print("<tr>\n");
+	this.stream.print("<td><h4>All ");
+	this.stream.print(computeSize(scenarios));
+	this.stream.print(" scenarios</h4></td>\n");
+	printColumnsTitle(size, performanceResults);
+
+	// Print one line per scenario results
+	for (int i=0; i<size; i++) {
+		ScenarioResults scenarioResults = (ScenarioResults) scenarios.get(i);
+		if (!scenarioResults.isValid()) continue;
+		this.stream.print("<tr>\n");
+		this.stream.print("<td>");
+		boolean hasSummary = scenarioResults.hasSummary();
+		if (hasSummary) this.stream.print("<b>");
+		this.stream.print(scenarioResults.getShortName());
+		if (hasSummary) this.stream.print("</b>");
+		this.stream.print("\n");
+		String[] configs = performanceResults.getConfigNames(true/*sort*/);
+		int length = configs.length;
+		for (int j=0; j<length; j++) {
+			printConfigStats(scenarioResults, configs[j]);
+		}
+	}
+	this.stream.print("</table>\n");
+}
+
+private int computeSize(List scenarios) {
+	int size = scenarios.size();
+	int n = 0;
+	for (int i=0; i<size; i++) {
+		ScenarioResults scenarioResults = (ScenarioResults) scenarios.get(i);
+		if (scenarioResults.isValid()) n++;
+	}
+	return n;
+}
+
+/*
+ * Print the table columns title.
+ */
+private void printColumnsTitle(int size, PerformanceResults performanceResults) {
+	String[] configNames = performanceResults.getConfigNames(true/*sort*/);
+	String[] configBoxes = performanceResults.getConfigBoxes(true/*sort*/);
+	int length = configNames.length;
+	for (int i=0; i<length; i++) {
+		String columnTitle = configNames[i];
+		String boxName = configBoxes[i];
+		int idx = boxName.indexOf('(');
+		if (idx < 0) {
+			columnTitle = boxName;
+		} else {
+			// first line
+			StringTokenizer tokenizer = new StringTokenizer(boxName.substring(0, idx).trim(), " ");
+			StringBuffer buffer = new StringBuffer(tokenizer.nextToken());
+			while (tokenizer.hasMoreTokens()) {
+				buffer.append("&nbsp;");
+				buffer.append(tokenizer.nextToken());
+			}
+			buffer.append(' ');
+			// second line
+			tokenizer = new StringTokenizer(boxName.substring(idx).trim(), " ");
+			buffer.append(tokenizer.nextToken());
+			while (tokenizer.hasMoreTokens()) {
+				buffer.append("&nbsp;");
+				buffer.append(tokenizer.nextToken());
+			}
+			columnTitle = buffer.toString();
+		}
+		this.stream.print("<td><h5>");
+		this.stream.print(columnTitle);
+		this.stream.print("</h5>\n");
+	}
+}
+
+/*
+ * Print the scenario statistics value for the given configuration.
+ */
+private void printConfigStats(ScenarioResults scenarioResults, String config) {
+	ConfigResults configResults = scenarioResults.getConfigResults(config);
+	if (configResults == null || !configResults.isValid()) {
+		this.stream.print("<td>n/a</td>");
+		return;
+	}
+	final BuildResults buildResults = configResults.getBuildResults(this.buildName);
+	if (buildResults == null) {
+		this.stream.print("<td>no results</td>");
+		return;
+	}
+	final BuildResults referenceResults = configResults.getBuildResults(this.referenceName);
+	if (referenceResults == null) {
+		this.stream.print("<td>no reference</td>");
+		return;
+	}
+	double[] numbers = configResults.getNumbers(buildResults, referenceResults);
+	final double delta = numbers[AbstractResults.DELTA_VALUE_INDEX];
+	final double[] deviation = new double[] { -delta, numbers[AbstractResults.DELTA_ERROR_INDEX] };
+	boolean hasFailure = delta < -DEFAULT_FAILURE_THRESHOLD;
+	String comment = buildResults.getComment();
+	String image = Utils.getImage(0, hasFailure, comment != null);
+	this.stream.print("<td><a ");
+
+	// write deviation with error in table
+	this.stream.print("href=\"http://fullmoon.ottawa.ibm.com/downloads/drops/I20100817-0800/performance/");
+	this.stream.print(configResults.getName());
+	this.stream.print('/');
+	this.stream.print(scenarioResults.getFileName());
+	this.stream.print(".html\">\n");
+	this.stream.print("<img hspace=\"10\" border=\"0\" src=\"");
+	this.stream.print(image);
+	this.stream.print("\"/></a>\n");
+	String result = Utils.failureMessage(deviation, false);
+	this.stream.print(result);
+	this.stream.print("\n");
+}
+
+/*
+ * Print the comparison table title.
+ */
+private void printTitle() {
+	this.stream.print("<br><h3>Component ");
+	this.stream.print(this.component);
+	this.stream.print("</h3>\n");
+}
+
+}
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsComparisonView.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsComparisonView.java
new file mode 100644
index 0000000..5616059
--- /dev/null
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsComparisonView.java
@@ -0,0 +1,404 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.test.internal.performance.results.ui;
+
+import java.io.File;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.test.internal.performance.results.model.BuildResultsElement;
+import org.eclipse.test.internal.performance.results.model.PerformanceResultsElement;
+import org.eclipse.test.internal.performance.results.utils.IPerformancesConstants;
+import org.eclipse.test.internal.performance.results.utils.Util;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.ViewPart;
+
+
+/**
+ * This view shows the difference between two selected builds.
+ * <p>
+ * Each component are shown in a separate tab.
+ * </p><p>
+ * The displayed results can be written in a file, either all component or only
+ * the current one.
+ * </p><p>
+ * It's also possible to filter the scenario to display only the fingerprint ones.
+ * <br>
+ * Note that this filter is synchronized with the one applied in the
+ * {@link ComponentsView Components view}.
+ * </p>
+ *
+ * @see ConfigTab Folder tab containing all the results for a configuration.
+ */
+public class BuildsComparisonView extends ViewPart implements ISelectionChangedListener, IPreferenceChangeListener {
+
+	// SWT resources
+	Shell shell;
+	CTabFolder tabFolder;
+
+	// Model information
+	BuildsComparisonTab[] tabs;
+	PerformanceResultsElement results;
+
+	// Action
+	Action filterAdvancedScenarios;
+	Action writeComparison;
+
+	// Write Status
+	static int WRITE_STATUS;
+
+	// Views
+	BuildsView buildsView;
+	IMemento viewState;
+
+	// Eclipse preferences
+	IEclipsePreferences preferences;
+
+	// Comparison
+	String currentBuild;
+	String referenceBuild;
+
+/*
+ * Default constructor:
+ * 	- create the image descriptor
+ * 	- register the view as a properties listener
+ */
+public BuildsComparisonView() {
+	this.preferences = new InstanceScope().getNode(IPerformancesConstants.PLUGIN_ID);
+	this.preferences.addPreferenceChangeListener(this);
+	// TODO should be done only once!
+	Util.initMilestones(this.preferences);
+}
+
+/*
+ * Contribute the local tools bar and the pull-down menu to the action bars.
+ */
+void contributeToActionBars() {
+	IActionBars bars = getViewSite().getActionBars();
+	fillLocalPullDown(bars.getMenuManager());
+	fillLocalToolBar(bars.getToolBarManager());
+}
+
+/*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
+ */
+public void createPartControl(Composite parent) {
+
+	// Create the tab folder
+	this.shell = parent.getShell ();
+	this.tabFolder = new CTabFolder(parent, SWT.BORDER);
+
+	// Add results view as listener to viewer selection changes
+	Display.getDefault().asyncExec(new Runnable() {
+		public void run() {
+			PerformancesView performancesView = (PerformancesView) PerformancesView.getWorkbenchView("org.eclipse.test.internal.performance.results.ui.ComponentsView");
+			if (performancesView != null) {
+				performancesView.viewer.addSelectionChangedListener(BuildsComparisonView.this);
+			}
+		}
+	});
+
+	// Set actions
+	PlatformUI.getWorkbench().getHelpSystem().setHelp(this.tabFolder, "org.eclipse.test.performance.ui.results");
+	makeActions();
+	contributeToActionBars();
+
+	// Restore state
+	restoreState();
+
+	// Create tabs
+	createTabs();
+
+	// Set selections (tab and line)
+	this.tabFolder.setSimple(false);
+}
+
+/*
+ * Create the tab folder pages. There's one tab per performance machine.
+ * The list of these machines is got from the DB_Results contants.
+ */
+void createTabs() {
+	if (this.currentBuild == null || this.referenceBuild == null) return;
+	PerformanceResultsElement performanceResultsElement = getBuildsView().results;
+	String[] components = performanceResultsElement.getComponents();
+	int length = components.length;
+	this.tabs = new BuildsComparisonTab[length];
+	for (int i=0; i<length; i++) {
+		this.tabs[i] = new BuildsComparisonTab(components[i]);
+	}
+	for (int i=0; i<this.tabs.length; i++) {
+		CTabItem item = new CTabItem (this.tabFolder, SWT.NONE);
+		item.setText (this.tabs[i].getTabText ());
+		item.setControl (this.tabs[i].createTabFolderPage(this));
+		item.setData (this.tabs[i]);
+	}
+	this.tabFolder.setSelection(0);
+}
+
+/*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.part.WorkbenchPart#dispose()
+ */
+public void dispose() {
+	this.tabFolder.dispose();
+	int length = this.tabs==null ? 0 : this.tabs.length;
+	for (int i=0; i<length; i++) {
+		this.tabs[i].dispose();
+	}
+	super.dispose();
+}
+
+/*
+ * Fill the filters drop-down menu with:
+ * 	- filter nightly builds
+ * 	- filter non-milestone builds
+ *	- filter non-fingerprint scenarios
+ */
+void fillFiltersDropDown(IMenuManager manager) {
+	manager.add(this.filterAdvancedScenarios);
+}
+
+/*
+ * Fill the local pull down menu.
+ */
+void fillLocalPullDown(IMenuManager manager) {
+	MenuManager filtersManager= new MenuManager("Filters");
+	fillFiltersDropDown(filtersManager);
+	manager.add(filtersManager);
+}
+
+/*
+ * Fill the local tool bar with:
+ * 	- change line selection display
+ */
+void fillLocalToolBar(IToolBarManager manager) {
+	manager.add(this.writeComparison);
+}
+
+/*
+ * Return the components results view.
+ */
+PerformanceResultsElement getResults() {
+	if (this.results == null) {
+		this.results = getBuildsView().results;
+	}
+	return this.results;
+}
+
+/*
+ * Return the components results view.
+ */
+BuildsView getBuildsView() {
+	if (this.buildsView == null) {
+		this.buildsView = (BuildsView) PerformancesView.getWorkbenchView("org.eclipse.test.internal.performance.results.ui.BuildsView");
+	}
+	return this.buildsView;
+}
+
+/*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.part.ViewPart#init(org.eclipse.ui.IViewSite, org.eclipse.ui.IMemento)
+ */
+public void init(IViewSite site, IMemento memento) throws PartInitException {
+	super.init(site, memento);
+	this.viewState = memento;
+}
+
+/*
+ * Make the actions of the view:
+ * 	- change table line selection display
+ * 	- filter nightly builds
+ * 	- filter non-milestone builds
+ *	- filter non-fingerprint scenarios
+ */
+void makeActions() {
+
+	// Filter non-fingerprints action
+	this.filterAdvancedScenarios = new Action("Advanced &Scenarios", IAction.AS_CHECK_BOX) {
+		public void run() {
+			BuildsComparisonView.this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, isChecked());
+			resetTabFolders(false/*refresh*/);
+        }
+	};
+	this.filterAdvancedScenarios.setChecked(true);
+	this.filterAdvancedScenarios.setToolTipText("Filter advanced scenarios (i.e. not fingerprint ones)");
+
+	// Write comparison
+	this.writeComparison = new Action("Write comparison") {
+		public void run() {
+
+			// Get write directory
+			BuildsView bView = getBuildsView();
+			String filter = (bView.resultsDir == null) ? null : bView.resultsDir.getPath();
+			final File writeDir = bView.changeDir(filter, "Select a directory to write the comparison between two builds");
+			if (writeDir != null) {
+				writeComparison(writeDir);
+			}
+        }
+	};
+	this.writeComparison.setEnabled(false);
+	this.writeComparison.setToolTipText("Write comparison between two builds");
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent)
+ */
+public void preferenceChange(PreferenceChangeEvent event) {
+	String propertyName = event.getKey();
+	Object newValue = event.getNewValue();
+
+	// Filter non-fingerprints change
+	if (propertyName.equals(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS)) {
+		boolean checked = newValue == null ? IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS : "true".equals(newValue);
+		this.filterAdvancedScenarios.setChecked(checked);
+		resetTabFolders(false/*refresh*/);
+	}
+}
+
+/*
+ * Reset the table tab folders by re-create all the pages.
+ * Selections are set onto the first found error if this is the first tab creation (typically on a component change event from the ComponentsView)
+ * or to the previous one if this is just a refresh.
+ */
+void resetTabFolders(boolean init) {
+
+	// Store current indexes
+	int tabIndex = this.tabFolder.getSelectionIndex();
+	int lineIndex = tabIndex<0 ? -1 : this.tabs[tabIndex].table.getSelectionIndex();
+
+	// Create tab folders
+	CTabItem[] tabItems = this.tabFolder.getItems();
+	int length = tabItems.length;
+	if (length == 0) {
+		createTabs();
+	} else {
+		for (int i=0; i<length; i++) {
+			tabItems[i].setControl(this.tabs [i].createTabFolderPage(this));
+		}
+	}
+
+	// Set part name
+	setPartName(this.currentBuild+" vs. "+this.referenceBuild);
+
+	// Set the selection
+	if (tabIndex >= 0 && lineIndex >= 0) {
+		this.tabFolder.setSelection(tabIndex);
+		Table table = this.tabs[tabIndex].table;
+		table.setSelection(lineIndex);
+	}
+}
+
+/*
+ * Restore the view state from the memento information.
+ */
+void restoreState() {
+
+	// Filter non fingerprints action state
+	boolean checked = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS);
+	this.filterAdvancedScenarios.setChecked(checked);
+}
+
+/*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.part.ViewPart#saveState(org.eclipse.ui.IMemento)
+ */
+public void saveState(IMemento memento) {
+	super.saveState(memento);
+}
+
+/*
+ * (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+ */
+public void selectionChanged(SelectionChangedEvent event) {
+	final Object[] selection = ((TreeSelection) event.getSelection()).toArray();
+	String firstBuildResults = null;
+	String secondBuildResults = null;
+	if (selection.length == 2) {
+		this.tabFolder.setVisible(true);
+		if (selection[0] instanceof BuildResultsElement) {
+			firstBuildResults = ((BuildResultsElement) selection[0]).getName();
+		}
+		if (selection[1] instanceof BuildResultsElement) {
+			secondBuildResults = ((BuildResultsElement) selection[1]).getName();
+		}
+		if (!firstBuildResults.equals(this.currentBuild) || !secondBuildResults.equals(this.referenceBuild)) {
+			this.currentBuild = firstBuildResults;
+			this.referenceBuild = secondBuildResults;
+			resetTabFolders(true);
+		}
+		this.writeComparison.setEnabled(true);
+	} else {
+		this.writeComparison.setEnabled(false);
+		this.tabFolder.setVisible(false);
+	}
+}
+
+/*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
+ */
+public void setFocus() {
+	// do nothing
+}
+
+protected void writeComparison(File writeDir) {
+	getBuildsView().resultsDir = writeDir;
+	writeDir = new File(writeDir, "values");
+	if (this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, false)) {
+		writeDir = new File(writeDir, "fingerprints");
+	} else {
+		writeDir = new File(writeDir, "all");
+	}
+	writeDir.mkdirs();
+	String buildDate = this.currentBuild.substring(1);
+	String buildPrefix = "Comparison" + buildDate + "_" + this.currentBuild.charAt(0);
+	File resultsFile = new File(writeDir, buildPrefix+".html");
+	if (resultsFile.exists()) {
+		int i=0;
+		File saveDir = new File(writeDir, "save");
+		saveDir.mkdir();
+		while (true) {
+			String newFileName = buildPrefix+"_";
+			if (i<10) newFileName += "0";
+			newFileName += i;
+			File renamedFile = new File(saveDir, newFileName+".html");
+			if (resultsFile.renameTo(renamedFile)) {
+				break;
+			}
+			i++;
+		}
+	}
+	this.results.writeComparison(resultsFile, this.currentBuild, this.referenceBuild);
+}
+
+}
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsView.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsView.java
index 3dabb41..dd011ca 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsView.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/BuildsView.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
  * 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
@@ -11,7 +11,12 @@
 package org.eclipse.test.internal.performance.results.ui;
 
 
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
 import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.lang.reflect.InvocationTargetException;
@@ -27,6 +32,7 @@
 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
 import org.eclipse.jface.operation.IRunnableWithProgress;
 import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.LabelProvider;
 import org.eclipse.jface.viewers.SelectionChangedEvent;
@@ -38,6 +44,7 @@
 import org.eclipse.swt.graphics.Font;
 import org.eclipse.swt.graphics.FontData;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
 import org.eclipse.test.internal.performance.results.db.DB_Results;
 import org.eclipse.test.internal.performance.results.model.BuildResultsElement;
 import org.eclipse.test.internal.performance.results.model.ResultsElement;
@@ -112,45 +119,17 @@
 			final boolean fingerprints = MessageDialog.openQuestion(BuildsView.this.shell, getTitleToolTip(), "Generate only fingerprints?");
 
 			// Generate all selected builds
-			int length = BuildsView.this.buildsResults.length;
-			for (int i = 0; i < length; i++) {
-				generate(i, baselineName, fingerprints);
-			}
-		}
-
-		/*
-		 * Generate the HTML pages.
-		 */
-		private void generate(int i, final String baselineName, final boolean fingerprints) {
-			// Create output directory
-			final String buildName = BuildsView.this.buildsResults[i].getName();
-			final File genDir = new File(BuildsView.this.outputDir, buildName);
-			if (!genDir.exists() && !genDir.mkdir()) {
-				MessageDialog.openError(BuildsView.this.shell, getTitleToolTip(), "Cannot create " + genDir.getPath() + " to generate results!");
-				return;
-			}
-
-			// Create runnable
 			IRunnableWithProgress runnable = new IRunnableWithProgress() {
-
 				public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
 					try {
-						monitor.beginTask("Generate performance results", 10000);
-						GenerateResults generation = new GenerateResults(BuildsView.this.results.getPerformanceResults(),
-						    buildName,
-						    baselineName,
-						    fingerprints,
-						    BuildsView.this.dataDir,
-						    genDir);
-						GenerateAction.this.status = generation.run(monitor);
+						monitor.beginTask("Generate performance results", BuildsView.this.buildsResults.length*2);
+						generate(baselineName, fingerprints, monitor);
 						monitor.done();
 					} catch (Exception e) {
 						e.printStackTrace();
 					}
 				}
 			};
-
-			// Run with progress monitor
 			ProgressMonitorDialog readProgress = new ProgressMonitorDialog(getSite().getShell());
 			try {
 				readProgress.run(true, true, runnable);
@@ -160,6 +139,54 @@
 				// skip
 			}
 
+		}
+
+		void generate(final String baselineName, final boolean fingerprints, IProgressMonitor monitor) {
+
+			// Generate result for the build
+			GenerateResults generation = new GenerateResults(fingerprints, BuildsView.this.dataDir);
+
+			// Loop on selected builds
+			final String lastBuildName = BuildsView.this.lastBuild == null ? DB_Results.getLastCurrentBuild() : BuildsView.this.lastBuild;
+			String previousBuild = lastBuildName;
+			int length = BuildsView.this.buildsResults.length;
+			for (int i=0; i<length; i++) {
+
+				BuildResultsElement currentBuild = BuildsView.this.buildsResults[i];
+				String buildName = currentBuild.getName();
+				monitor.setTaskName("Generate perf results for build "+buildName);
+
+				// Create output directory
+				File genDir = new File(BuildsView.this.outputDir, buildName);
+				if (!genDir.exists() && !genDir.mkdir()) {
+					MessageDialog.openError(BuildsView.this.shell, getTitleToolTip(), "Cannot create " + genDir.getPath() + " to generate results!");
+					return;
+				}
+
+				// See if it's necessary to refresh data
+				if (!buildName.equals(previousBuild)) {
+					monitor.subTask("Get local data...");
+					BuildsView.this.results.readLocal(BuildsView.this.dataDir, null, buildName);
+					monitor.worked(1);
+				}
+
+				// Generate result for the build
+				GenerateAction.this.status = generation.run(BuildsView.this.results.getPerformanceResults(), buildName, baselineName, genDir, monitor);
+
+				// Store previous build
+				previousBuild = buildName;
+				if (monitor.isCanceled()) {
+					break;
+				}
+			}
+
+			// Refresh data if necessary
+			if (!lastBuildName.equals(previousBuild)) {
+				monitor.subTask("Put back local data for "+lastBuildName+"...");
+				BuildsView.this.results.readLocal(BuildsView.this.dataDir, null, BuildsView.this.lastBuild);
+				monitor.worked(1);
+			}
+
 			// Results
 			if (!this.status.isOK()) {
 				StringWriter swriter = new StringWriter();
@@ -200,7 +227,7 @@
 
 			// Verify that directories are set
 			if (BuildsView.this.dataDir == null) {
-				if (changeDataDir() == null) {
+				if (changeDataDir(null) == null) {
 					if (!MessageDialog.openConfirm(BuildsView.this.shell, getTitleToolTip(), "No local files directory is set, hence the update could not be written! OK to continue?")) {
 						return;
 					}
@@ -273,18 +300,21 @@
 	}
 
 	// Views
-	PerformancesView componentsView;
+	ComponentsView componentsView;
+	BuildsComparisonView buildsComparisonView = null;
 
 	// Results model
 	BuildResultsElement[] buildsResults;
+	String lastBuild;
 
-	// Generation info
+	// Directories
 	File outputDir;
 
 	// Actions
 	Action generate;
 	UpdateBuildAction updateBuild, updateAllBuilds;
 //	UpdateBuildAction forceUpdateBuild, forceUpdateAllBuilds;
+	Action writeBuildsFailures;
 
 	// SWT resources
 	Font italicFont;
@@ -381,6 +411,16 @@
 	};
 	this.viewer.setSorter(nameSorter);
 
+	// Add results view as listener to viewer selection changes
+	Display.getDefault().asyncExec(new Runnable() {
+		public void run() {
+			ISelectionChangedListener listener = getComparisonView();
+			if (listener != null) {
+				BuildsView.this.viewer.addSelectionChangedListener(listener);
+			}
+		}
+	});
+
 	// Finalize viewer initialization
 	PlatformUI.getWorkbench().getHelpSystem().setHelp(this.viewer.getControl(), "org.eclipse.test.performance.ui.builds");
 	finalizeViewerCreation();
@@ -405,15 +445,8 @@
 	manager.add(this.generate);
 	manager.add(this.updateBuild);
 //	manager.add(this.forceUpdateBuild);
-}
-
-/*
- * (non-Javadoc)
- * @see org.eclipse.test.internal.performance.results.ui.PerformancesView#fillLocalPullDown(org.eclipse.jface.action.IMenuManager)
- */
-void fillFiltersDropDown(IMenuManager manager) {
-	super.fillFiltersDropDown(manager);
-	manager.add(this.filterLastBuilds);
+	manager.add(new Separator());
+	manager.add(this.writeBuildsFailures);
 }
 
 /*
@@ -431,17 +464,28 @@
  */
 Object[] getBuilds() {
 	if (this.results == null) {
+//		initResults(this.lastBuild);
 		initResults();
 	}
 	return this.results.getBuilds();
 }
 
 /*
+ * Return the components results view.
+ */
+BuildsComparisonView getComparisonView() {
+	if (this.buildsComparisonView == null) {
+		this.buildsComparisonView = (BuildsComparisonView) getWorkbenchView("org.eclipse.test.internal.performance.results.ui.BuildsComparisonView");
+	}
+	return this.buildsComparisonView;
+}
+
+/*
  * Return the components view.
  */
 PerformancesView getSiblingView() {
 	if (this.componentsView == null) {
-		this.componentsView = (PerformancesView) getWorkbenchView("org.eclipse.test.internal.performance.results.ui.ComponentsView");
+		this.componentsView = (ComponentsView) getWorkbenchView("org.eclipse.test.internal.performance.results.ui.ComponentsView");
 	}
 	return this.componentsView;
 }
@@ -473,6 +517,46 @@
 //	this.forceUpdateAllBuilds = new UpdateAllBuildsAction(true);
 //	this.forceUpdateAllBuilds.setText("Force Update all");
 
+	// Write status
+	this.writeBuildsFailures = new Action("Write failures") {
+		public void run() {
+			String filter = (BuildsView.this.resultsDir == null) ? null : BuildsView.this.resultsDir.getPath();
+			final File writeDir = changeDir(filter, "Select a directory to write the files");
+			if (writeDir != null) {
+
+				// Create runnable
+				IRunnableWithProgress runnable = new IRunnableWithProgress() {
+
+					public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+						try {
+							monitor.beginTask("Write failures", BuildsView.this.buildsResults.length*2);
+							writeBuildsFailures(writeDir, monitor);
+							monitor.done();
+						} catch (Exception e) {
+							e.printStackTrace();
+						}
+					}
+				};
+
+				// Run with progress monitor
+				ProgressMonitorDialog readProgress = new ProgressMonitorDialog(getSite().getShell());
+				try {
+					readProgress.run(true, true, runnable);
+				} catch (InvocationTargetException e) {
+					// skip
+				} catch (InterruptedException e) {
+					// skip
+				}
+
+				// Refresh views
+				refreshInput();
+				getSiblingView().refreshInput();
+			}
+        }
+	};
+	this.writeBuildsFailures.setEnabled(true);
+	this.writeBuildsFailures.setToolTipText("Write component status to a file");
+
 	// Set filters default
 	this.filterBaselineBuilds.setChecked(false);
 	this.filterNightlyBuilds.setChecked(false);
@@ -489,44 +573,22 @@
 	int eclipseVersion = this.preferences.getInt(IPerformancesConstants.PRE_ECLIPSE_VERSION, IPerformancesConstants.DEFAULT_ECLIPSE_VERSION);
 	boolean connected = this.preferences.getBoolean(IPerformancesConstants.PRE_DATABASE_CONNECTION, IPerformancesConstants.DEFAULT_DATABASE_CONNECTION);
 	String databaseLocation = this.preferences.get(IPerformancesConstants.PRE_DATABASE_LOCATION, IPerformancesConstants.NETWORK_DATABASE_LOCATION);
-	String lastBuild = this.preferences.get(IPerformancesConstants.PRE_LAST_BUILD, null);
-	boolean noLastBuild = lastBuild.length() == 0;
 	if (debug) {
 		System.out.println("Reset View:");
 		System.out.println("	- eclispe version = "+eclipseVersion);
 		System.out.println("	- connected       = "+connected);
 		System.out.println("	- db location     = "+databaseLocation);
-		System.out.println("	- last build      = "+(noLastBuild?"<none>":lastBuild));
 	}
 	final boolean sameVersion = DB_Results.getDbVersion().endsWith(Integer.toString(eclipseVersion));
 	final boolean sameConnection = connected == DB_Results.DB_CONNECTION;
 	final boolean sameDB = sameVersion && databaseLocation.equals(DB_Results.getDbLocation());
-	boolean sameLastBuild = (noLastBuild && LAST_BUILD == null) || lastBuild.equals(LAST_BUILD);
 	if (debug) {
 		System.out.println("	- same version:    "+sameVersion);
 		System.out.println("	- same connection: "+sameConnection);
 		System.out.println("	- same DB:         "+sameDB);
-		System.out.println("	- same last build: "+sameLastBuild);
 	}
 	final PerformancesView siblingView = getSiblingView();
 	if (sameConnection && sameDB) {
-		if (!sameLastBuild) {
-			// Set last build
-			LAST_BUILD = noLastBuild ? null : lastBuild;
-			this.results.setLastBuildName(LAST_BUILD);
-			siblingView.results.setLastBuildName(LAST_BUILD);
-
-			// Reset views content
-			resetInput();
-			siblingView.resetInput();
-
-			// May be read local data now
-			File newDataDir = changeDataDir();
-			if (newDataDir == null) {
-				this.dataDir = null;
-				siblingView.dataDir = null;
-			}
-		}
 		// No database preferences has changed do nothing
 		return;
 	}
@@ -552,7 +614,7 @@
 	siblingView.setTitleToolTip();
 
 	// Refresh view
-	if (sameVersion && sameLastBuild) {
+	if (sameVersion) {
 		// Refresh only builds view as the sibling view (Components) contents is based on local data files contents
 		this.results.resetBuildNames();
 		refreshInput();
@@ -563,7 +625,7 @@
 
 		// May be read local data now
 		if (MessageDialog.openQuestion(this.shell, getTitleToolTip(), "Do you want to read local data right now?")) {
-			changeDataDir();
+			changeDataDir(this.lastBuild);
 		} else {
 			this.dataDir = null;
 			siblingView.dataDir = null;
@@ -585,6 +647,7 @@
 	// Update selected element
 	Object selection = this.viewer.getSelection();
 	int length = 0;
+	this.writeBuildsFailures.setEnabled(false);
 	if (selection instanceof IStructuredSelection) {
 		Object[] elements = ((IStructuredSelection)selection).toArray();
 		length = elements == null ? 0 : elements.length;
@@ -596,6 +659,7 @@
 		for (int i=0; i<length; i++) {
 			this.buildsResults[i] = (BuildResultsElement) elements[i];
 		}
+		this.writeBuildsFailures.setEnabled(true);
 	} else {
 		return;
 	}
@@ -634,7 +698,7 @@
 
 void updateAllBuilds(IProgressMonitor monitor, boolean force) {
 	if (this.dataDir == null) {
-		changeDataDir();
+		changeDataDir(null);
 	}
 	String[] builds = buildsToUpdate();
 	if (builds == null) {
@@ -646,7 +710,7 @@
 
 void updateBuilds(IProgressMonitor monitor, boolean force) {
 	if (this.dataDir == null) {
-		changeDataDir();
+		changeDataDir(null);
 	}
 	int length = this.buildsResults.length;
 	String[] builds = new String[length];
@@ -656,4 +720,110 @@
 	this.results.updateBuilds(builds, force, this.dataDir, monitor);
 }
 
+protected void writeBuildsFailures(File writeDir, IProgressMonitor monitor) {
+
+	// Loop on selected builds
+	final String lastBuildName = this.lastBuild == null ? DB_Results.getLastCurrentBuild() : this.lastBuild;
+	String previousBuild = lastBuildName;
+	int length = this.buildsResults.length;
+	for (int i=0; i<length; i++) {
+
+		// See if it's necessary to refresh data
+		BuildResultsElement currentBuild = this.buildsResults[i];
+		String currentBuildName = currentBuild.getName();
+		monitor.setTaskName("Write failures for build "+currentBuildName);
+		if (!currentBuildName.equals(previousBuild)) {
+			monitor.subTask("Get local data...");
+			this.results.readLocal(this.dataDir, null, currentBuildName);
+			monitor.worked(1);
+		}
+
+		// Write the failures for the selected build
+		monitor.subTask("write file...");
+		writeFailures(writeDir, currentBuildName);
+		monitor.worked(1);
+
+		// Store previous build
+		previousBuild = currentBuildName;
+		if (monitor.isCanceled()) {
+			return;
+		}
+	}
+
+	// Refresh data if necessary
+	if (!lastBuildName.equals(previousBuild)) {
+		monitor.subTask("Put back local data for "+lastBuildName+"...");
+		this.results.readLocal(this.dataDir, null, this.lastBuild);
+		monitor.worked(1);
+	}
+}
+
+protected void writeFailures(File writeDir, String buildName) {
+
+	// Set the write directory
+	this.resultsDir = writeDir;
+	boolean filterAdvancedScenarios = 	this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS);
+	if (filterAdvancedScenarios) {
+		writeDir = new File(writeDir, "fingerprints");
+	} else {
+		writeDir = new File(writeDir, "all");
+	}
+	writeDir.mkdir();
+	int writeStatusValue = this.preferences.getInt(IPerformancesConstants.PRE_WRITE_STATUS, IPerformancesConstants.DEFAULT_WRITE_STATUS);
+	if ((writeStatusValue & IPerformancesConstants.STATUS_VALUES) != 0) {
+		writeDir = new File(writeDir, "values");
+	}
+	int buildsNumber = writeStatusValue & IPerformancesConstants.STATUS_BUILDS_NUMBER_MASK;
+	if (buildsNumber > 1) {
+		writeDir = new File(writeDir, Integer.toString(buildsNumber));
+	}
+	writeDir.mkdirs();
+
+	// Create the written file
+	String buildDate = buildName.substring(1);
+	String buildPrefix = buildDate + "_" + buildName.charAt(0);
+	File resultsFile = new File(writeDir, buildPrefix+".log");
+	File exclusionDir = new File(writeDir, "excluded");
+	exclusionDir.mkdir();
+	File exclusionFile = new File(exclusionDir, buildPrefix+".log");
+	if (resultsFile.exists()) {
+		int i=0;
+		File saveDir = new File(writeDir, "save");
+		saveDir.mkdir();
+		while (true) {
+			String newFileName = buildPrefix+"_";
+			if (i<10) newFileName += "0";
+			newFileName += i;
+			File renamedFile = new File(saveDir, newFileName+".log");
+			if (resultsFile.renameTo(renamedFile)) {
+				File renamedExclusionFile = new File(exclusionDir, newFileName+".log");
+				exclusionFile.renameTo(renamedExclusionFile);
+				break;
+			}
+			i++;
+		}
+	}
+
+	// Write status
+	StringBuffer excluded = this.results.writeFailures(resultsFile, writeStatusValue);
+	if (excluded == null) {
+		MessageDialog.openWarning(this.shell, getTitleToolTip(), "The component is not read, hence no results can be written!");
+	}
+
+	// Write exclusion file
+	try {
+		DataOutputStream stream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(exclusionFile)));
+		try {
+			stream.write(excluded.toString().getBytes());
+		}
+		finally {
+			stream.close();
+		}
+	} catch (FileNotFoundException e) {
+		System.err.println("Can't create exclusion file"+exclusionFile); //$NON-NLS-1$
+	} catch (IOException e) {
+		e.printStackTrace();
+	}
+}
+
 }
\ No newline at end of file
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/ComponentResultsView.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/ComponentResultsView.java
index 158361d..d166c3d 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/ComponentResultsView.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/ComponentResultsView.java
@@ -10,8 +10,6 @@
  *******************************************************************************/
 package org.eclipse.test.internal.performance.results.ui;
 
-import java.util.StringTokenizer;
-
 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.core.runtime.preferences.InstanceScope;
 import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
@@ -81,9 +79,6 @@
  */
 public class ComponentResultsView extends ViewPart implements ISelectionChangedListener, IPreferenceChangeListener {
 
-	// Constants
-	private static final String ORG_ECLIPSE = "org.eclipse.";
-
 	// SWT resources
 	CTabFolder tabFolder;
 
@@ -337,7 +332,7 @@
 
 	// Set the part name when possible
 	if (this.componentResultsElement != null) {
-		setPartName();
+		setPartName(Util.componentDisplayName(this.componentResultsElement.getName()));
 	}
 
 	// If this is the first display then look for the first error to set the selection on it
@@ -486,7 +481,7 @@
  * 	- org.eclipse.jdt.ui -> "JDT/UI"
  * 	- org.eclipse.jdt.core -> "JDT/Core"
  * 	- org.eclipse.pde.api.tools -> "PDE/API Tools"
- */
+ *
 protected void setPartName() {
 	String componentName = this.componentResultsElement.getName();
 	String partName;
@@ -527,5 +522,6 @@
 	buffer.append("' results");
 	setPartName(buffer.toString());
 }
+*/
 
 }
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/ComponentsView.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/ComponentsView.java
index 06b77d3..9797fb0 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/ComponentsView.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/ComponentsView.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
  * 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
@@ -10,12 +10,6 @@
  *******************************************************************************/
 package org.eclipse.test.internal.performance.results.ui;
 
-import java.io.BufferedOutputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
@@ -26,7 +20,6 @@
 import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.jface.action.Separator;
-import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.resource.JFaceResources;
 import org.eclipse.jface.viewers.AbstractTreeViewer;
 import org.eclipse.jface.viewers.ISelectionChangedListener;
@@ -96,36 +89,26 @@
 	};
 
 	// Views
-	PerformancesView buildsView;
+	BuildsView buildsView;
 	ComponentResultsView componentResultsView = null;
 
 	// Internal
 	Set expandedComponents = new HashSet();
-	File resultsDir = null;
 
 	// Actions
 	Action filterAdvancedScenarios;
-	Action writeStatus;
 
 	// SWT resources
 	Font boldFont;
 
-	// Write Status
-	static int WRITE_STATUS;
-
 /**
  * Default constructor.
  */
 public ComponentsView() {
-//	this.onlyFingerprintsImageDescriptor = ImageDescriptor.createFromFile(getClass(), "filter_ps.gif");
 	super();
 
 	// Get preferences
 	this.preferences = new InstanceScope().getNode(IPerformancesConstants.PLUGIN_ID);
-
-	// Init status
-	WRITE_STATUS = this.preferences.getInt(IPerformancesConstants.PRE_WRITE_STATUS, IPerformancesConstants.DEFAULT_WRITE_STATUS);
-
 }
 
 /*
@@ -164,8 +147,6 @@
 		public Font getFont(Object element) {
 			Font font = super.getFont(element);
 			if (element instanceof ScenarioResultsElement) {
-//				Action fingerprints = ComponentsView.this.filterNonFingerprints;
-//				if (fingerprints != null && !fingerprints.isChecked()) {
 				boolean fingerprints = ComponentsView.this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_ADVANCED_SCENARIOS, IPerformancesConstants.DEFAULT_FILTER_ADVANCED_SCENARIOS);
 				if (!fingerprints) {
 					ScenarioResultsElement scenarioElement = (ScenarioResultsElement) element;
@@ -228,7 +209,6 @@
 	if (this.boldFont != null) {
 		this.boldFont.dispose();
 	}
-//	JFaceResources.getResources().destroyImage(this.onlyFingerprintsImageDescriptor);
 	super.dispose();
 }
 
@@ -239,17 +219,10 @@
 void fillFiltersDropDown(IMenuManager manager) {
 	super.fillFiltersDropDown(manager);
 	manager.add(this.filterOldBuilds);
-	manager.add(this.filterLastBuilds);
 	manager.add(new Separator());
 	manager.add(this.filterAdvancedScenarios);
 }
 
-void fillLocalPullDown(IMenuManager manager) {
-	super.fillLocalPullDown(manager);
-	manager.add(new Separator());
-	manager.add(this.writeStatus);
-}
-
 /*
  * Filter non fingerprints scenarios action run.
  */
@@ -304,7 +277,7 @@
  */
 PerformancesView getSiblingView() {
 	if (this.buildsView == null) {
-		this.buildsView = (PerformancesView) getWorkbenchView("org.eclipse.test.internal.performance.results.ui.BuildsView");
+		this.buildsView = (BuildsView) getWorkbenchView("org.eclipse.test.internal.performance.results.ui.BuildsView");
 	}
 	return this.buildsView;
 }
@@ -326,21 +299,6 @@
 	this.filterAdvancedScenarios.setChecked(true);
 	this.filterAdvancedScenarios.setToolTipText("Filter advanced scenarios (i.e. not fingerprint ones)");
 
-	// Write status
-	this.writeStatus = new Action("Write status") {
-		public void run() {
-
-			// Get write directory
-			String filter = (ComponentsView.this.resultsDir == null) ? null : ComponentsView.this.resultsDir.getPath();
-			final File writeDir = changeDir(filter, "Select a directory to write the status");
-			if (writeDir != null) {
-				writeStatus(writeDir);
-			}
-        }
-	};
-	this.writeStatus.setEnabled(true);
-	this.writeStatus.setToolTipText("Write component status to a file");
-
 	// Set filters default
 	this.filterBaselineBuilds.setChecked(true);
 	this.filterNightlyBuilds.setChecked(false);
@@ -367,11 +325,6 @@
 		this.filterOldBuilds.setChecked(checked);
 	}
 
-	// Write status
-	if (propertyName.equals(IPerformancesConstants.PRE_WRITE_STATUS)) {
-		WRITE_STATUS = newValue == null ? IPerformancesConstants.DEFAULT_WRITE_STATUS : Integer.parseInt((String)newValue);
-	}
-
 	super.preferenceChange(event);
 }
 
@@ -382,11 +335,6 @@
 	if (this.viewState == null) {
 		this.filterBaselineBuilds.setChecked(true);
 		this.viewFilters.add(FILTER_BASELINE_BUILDS);
-	} else {
-		String dir = this.viewState.getString(IPerformancesConstants.PRE_WRITE_RESULTS_DIR);
-		if (dir != null) {
-			this.resultsDir = new File(dir);
-		}
 	}
 
 	// Filter non fingerprints action state
@@ -398,9 +346,6 @@
 }
 
 public void saveState(IMemento memento) {
-	if (this.resultsDir != null) {
-		memento.putString(IPerformancesConstants.PRE_WRITE_RESULTS_DIR, this.resultsDir.getPath());
-	}
 	super.saveState(memento);
 }
 
@@ -449,65 +394,4 @@
 		}
 	}
 }
-
-protected void writeStatus(File writeDir) {
-		this.resultsDir = writeDir;
-		if (this.filterAdvancedScenarios.isChecked()) {
-			writeDir = new File(writeDir, "fingerprints");
-		} else {
-			writeDir = new File(writeDir, "all");
-		}
-		writeDir.mkdir();
-		if ((WRITE_STATUS & IPerformancesConstants.STATUS_VALUES) != 0) {
-			writeDir = new File(writeDir, "values");
-		}
-		int buildsNumber = WRITE_STATUS & IPerformancesConstants.STATUS_BUILDS_NUMBER_MASK;
-		if (buildsNumber > 1) {
-			writeDir = new File(writeDir, Integer.toString(buildsNumber));
-		}
-		writeDir.mkdirs();
-		String prefix = this.results.getName();
-		File resultsFile = new File(writeDir, prefix+".log");
-		File exclusionDir = new File(writeDir, "excluded");
-		exclusionDir.mkdir();
-		File exclusionFile = new File(exclusionDir, prefix+".log");
-		if (resultsFile.exists()) {
-			int i=0;
-			File saveDir = new File(writeDir, "save");
-			saveDir.mkdir();
-			while (true) {
-				String newFileName = prefix+"_";
-				if (i<10) newFileName += "0";
-				newFileName += i;
-				File renamedFile = new File(saveDir, newFileName+".log");
-				if (resultsFile.renameTo(renamedFile)) {
-					File renamedExclusionFile = new File(exclusionDir, newFileName+".log");
-					exclusionFile.renameTo(renamedExclusionFile);
-					break;
-				}
-				i++;
-			}
-		}
-
-		// Write status
-		StringBuffer excluded = this.results.writeStatus(resultsFile, WRITE_STATUS);
-		if (excluded == null) {
-			MessageDialog.openWarning(this.shell, getTitleToolTip(), "The component is not read, hence no results can be written!");
-		}
-
-		// Write exclusion file
-		try {
-			DataOutputStream stream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(exclusionFile)));
-			try {
-				stream.write(excluded.toString().getBytes());
-			}
-			finally {
-				stream.close();
-			}
-		} catch (FileNotFoundException e) {
-			System.err.println("Can't create exclusion file"+exclusionFile); //$NON-NLS-1$
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-}
 }
\ No newline at end of file
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPerspective.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPerspective.java
index eb0b54a..193489b 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPerspective.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPerspective.java
@@ -43,6 +43,7 @@
 			0.5f,
 			this.factory.getEditorArea());
 	bottom.addView("org.eclipse.test.internal.performance.results.ui.ComponentsResultsView");
+	bottom.addView("org.eclipse.test.internal.performance.results.ui.BuildsComparisonView");
 
 	// Components and Builds view put on perspective top left
 	IFolderLayout topLeft =
@@ -53,6 +54,7 @@
 			this.factory.getEditorArea());
 	topLeft.addView("org.eclipse.test.internal.performance.results.ui.ComponentsView"); //NON-NLS-1
 	topLeft.addView("org.eclipse.test.internal.performance.results.ui.BuildsView"); //NON-NLS-1
+	topLeft.addView(IPageLayout.ID_PROJECT_EXPLORER); //NON-NLS-1
 
 	// Properties view put on perspective top right
 	IFolderLayout topRight =
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPreferenceInitializer.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPreferenceInitializer.java
index d6bfb1d..d40edc3 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPreferenceInitializer.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPreferenceInitializer.java
@@ -43,6 +43,11 @@
 	// Status
 	defaultPreferences.putInt(PRE_WRITE_STATUS, IPerformancesConstants.DEFAULT_WRITE_STATUS);
 
+	// Comparison
+	defaultPreferences.putInt(PRE_COMPARISON_THRESHOLD_FAILURE, IPerformancesConstants.DEFAULT_COMPARISON_THRESHOLD_FAILURE);
+	defaultPreferences.putInt(PRE_COMPARISON_THRESHOLD_ERROR, IPerformancesConstants.DEFAULT_COMPARISON_THRESHOLD_ERROR);
+	defaultPreferences.putInt(PRE_COMPARISON_THRESHOLD_IMPROVEMENT, IPerformancesConstants.DEFAULT_COMPARISON_THRESHOLD_IMPROVEMENT);
+
 	// Config descriptors
 	String[][] configDescriptors = PerformanceTestPlugin.getConfigDescriptors();
 	int cdLength = configDescriptors.length;
@@ -69,13 +74,13 @@
 	defaultPreferences.putBoolean(PRE_FILTER_NIGHTLY_BUILDS, IPerformancesConstants.DEFAULT_FILTER_NIGHTLY_BUILDS);
 
 	// Milestones
-	String[] milestones = IPerformancesConstants.V35_MILESTONES;
+	String[] milestones = IPerformancesConstants.V36_MILESTONES;
 	String prefix = PRE_MILESTONE_BUILDS + "." + ECLIPSE_MAINTENANCE_VERSION;
 	length = milestones.length;
 	for (int i = 0; i < length; i++) {
 		defaultPreferences.put(prefix + i, milestones[i]);
 	}
-	milestones = IPerformancesConstants.V36_MILESTONES;
+	milestones = IPerformancesConstants.V37_MILESTONES;
 	prefix = PRE_MILESTONE_BUILDS + "." + ECLIPSE_DEVELOPMENT_VERSION;
 	length = milestones.length;
 	for (int i = 0; i < length; i++) {
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPreferencePage.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPreferencePage.java
index d5c4b6b..72e691e 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPreferencePage.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformanceResultsPreferencePage.java
@@ -11,7 +11,6 @@
 package org.eclipse.test.internal.performance.results.ui;
 
 import java.io.File;
-import java.util.Arrays;
 import java.util.Iterator;
 
 import org.osgi.service.prefs.BackingStoreException;
@@ -64,7 +63,7 @@
 	private Button dbRelengRadioButton;
 	private Button dbLocalRadioButton;
 	private CCombo defaultDimensionCombo;
-	private CCombo lastBuildCombo;
+//	private CCombo lastBuildCombo;
 	private List resultsDimensionsList;
 	private CCombo milestonesCombo;
 	private Label dbLocationLabel;
@@ -82,6 +81,9 @@
 	private Button statusStatisticErraticRadioButton;
 	private Button statusStatisticUnstableRadioButton;
 	private Text statusBuildsToConfirm;
+	private Text comparisonThresholdFailure;
+	private Text comparisonThresholdError;
+	private Text comparisonThresholdImprovement;
 
 	// TODO See whether config descriptors need to be set as preferences or not...
 	// private Table configDescriptorsTable;
@@ -221,29 +223,31 @@
 		this.statusBuildsToConfirm = createTextField(statusGroup);
 		this.statusBuildsToConfirm.setToolTipText("The number of previous builds to take into account to confirm a regression");
 
+		// Comparison
+		Composite compositeComparison = createComposite(parent, 1, 3);
+		Group comparisonGroup = createGroup(compositeComparison, "Comparison", 1);
+		Group thresholdsGroup = createGroup(comparisonGroup, "Thresholds", 6);
+//		Composite compositeFailureThreshold = createComposite(comparisonGroup, 2, 2);
+		createLabel(thresholdsGroup, "Failure:", false);
+		this.comparisonThresholdFailure = createTextField(thresholdsGroup);
+		this.comparisonThresholdFailure.setToolTipText("The threshold in percentage to report a failure");
+		createLabel(thresholdsGroup, "Error:", false);
+		this.comparisonThresholdError = createTextField(thresholdsGroup);
+		this.comparisonThresholdError.setToolTipText("The threshold in percentage to report an error");
+		createLabel(thresholdsGroup, "Improvement:", false);
+		this.comparisonThresholdImprovement = createTextField(thresholdsGroup);
+		this.comparisonThresholdImprovement.setToolTipText("The threshold in percentage to report an improvement");
+
 		// Milestones
 		Composite compositeMilestones = createComposite(parent, 3, 1);
 		createLabel(compositeMilestones, "Milestones", false);
 		this.milestonesCombo = createCombo(compositeMilestones);
 		this.milestonesCombo.setToolTipText("Enter the date of the milestone as yyyymmddHHMM");
 
-		// Last build
-		StringBuffer tooltip = new StringBuffer("Select the last build to display performance results\n");
-		tooltip.append("If set then performance results won't be displayed for any build after this date...");
-		String tooltipText = tooltip.toString();
-		Composite compositeLastBuild = createComposite(parent, 3, 1);
-	//	this.lastBuildCheckBox = createCheckBox(compositeLastBuild, "Until last build");
-		createLabel(compositeLastBuild, "Last build: ", false);
-		this.lastBuildCombo = createCombo(compositeLastBuild);
-		this.lastBuildCombo.setEditable(false);
-		this.lastBuildCombo.setToolTipText(tooltipText);
-		this.lastBuildCombo.add("");
-		initBuildsList();
-
 		// Default dimension layout
-		tooltip = new StringBuffer("Select the default dimension which will be used for performance results\n");
+		StringBuffer tooltip = new StringBuffer("Select the default dimension which will be used for performance results\n");
 		tooltip.append("When changed, the new selected dimension is automatically added to the dimensions list below...");
-		tooltipText = tooltip.toString();
+		String tooltipText = tooltip.toString();
 		Composite compositeDefaultDimension = createComposite(parent, 3, 1);
 		createLabel(compositeDefaultDimension, "Default dimension: ", false);
 		this.defaultDimensionCombo = createCombo(compositeDefaultDimension);
@@ -432,9 +436,6 @@
 	return UiPlugin.getDefault().getPreferenceStore();
 }
 
-/**
- * @return
- */
 String getDialogTitle() {
 	String title = DB_Results.getDbTitle();
 	if (title == null) {
@@ -489,18 +490,6 @@
 	}
 }
 
-/*
- * Init he contents of the dimensions list controls.
- */
-private void initBuildsList() {
-	String[] builds = DB_Results.getBuilds();
-	Arrays.sort(builds, Util.BUILD_DATE_COMPARATOR);
-	int length = builds.length;
-	for (int i=length-1; i>=0; i--) {
-		this.lastBuildCombo.add(builds[i]);
-	}
-}
-
 /**
  * Initializes states of the controls using default values in the preference
  * store.
@@ -526,6 +515,11 @@
 	int writeStatus = store.getDefaultInt(PRE_WRITE_STATUS);
 	initStatusValues(writeStatus);
 
+	// Init comparison thresholds
+	this.comparisonThresholdFailure.setText(String.valueOf(store.getDefaultInt(PRE_COMPARISON_THRESHOLD_FAILURE)));
+	this.comparisonThresholdError.setText(String.valueOf(store.getDefaultInt(PRE_COMPARISON_THRESHOLD_ERROR)));
+	this.comparisonThresholdImprovement.setText(String.valueOf(store.getDefaultInt(PRE_COMPARISON_THRESHOLD_IMPROVEMENT)));
+
 	// Init eclipse version
 	this.mVersionRadioButton.setSelection(false);
 	this.dVersionRadionButton.setSelection(false);
@@ -547,16 +541,6 @@
 		milestone = store.getDefaultString(prefix + ++index);
 	}
 
-	// Init last build
-	String lastBuild = store.getDefaultString(PRE_LAST_BUILD);
-//	if (lastBuild.length() == 0) {
-//		this.lastBuildCheckBox.setSelection(false);
-//		this.lastBuildCombo.setEnabled(false);
-//	} else {
-//		this.lastBuildCombo.setEnabled(true);
-//	}
-	this.lastBuildCombo.setText(lastBuild);
-
 	// Init default default dimension
 	String defaultDimension = store.getDefaultString(PRE_DEFAULT_DIMENSION);
 	this.defaultDimensionCombo.setText(defaultDimension);
@@ -596,6 +580,11 @@
 	int writeStatus = store.getInt(PRE_WRITE_STATUS);
 	initStatusValues(writeStatus);
 
+	// Init comparison thresholds
+	this.comparisonThresholdFailure.setText(String.valueOf(store.getInt(PRE_COMPARISON_THRESHOLD_FAILURE)));
+	this.comparisonThresholdError.setText(String.valueOf(store.getInt(PRE_COMPARISON_THRESHOLD_ERROR)));
+	this.comparisonThresholdImprovement.setText(String.valueOf(store.getInt(PRE_COMPARISON_THRESHOLD_IMPROVEMENT)));
+
 	// Init eclipse version
 	int version = store.getInt(PRE_ECLIPSE_VERSION);
 	if (version == ECLIPSE_MAINTENANCE_VERSION) {
@@ -614,16 +603,6 @@
 		milestone = store.getString(prefix + ++index);
 	}
 
-	// Init last build
-	String lastBuild = store.getString(PRE_LAST_BUILD);
-//	if (lastBuild.length() == 0) {
-//		this.lastBuildCheckBox.setSelection(false);
-//		this.lastBuildCombo.setEnabled(false);
-//	} else {
-//		this.lastBuildCombo.setEnabled(true);
-//	}
-	this.lastBuildCombo.setText(lastBuild);
-
 	// Init composite lists
 	initDimensionsLists();
 
@@ -661,9 +640,6 @@
 	*/
 }
 
-/**
- * @param store
- */
 private void initStatusValues(int writeStatus) {
 	this.statusValuesCheckBox.setSelection((writeStatus & STATUS_VALUES) != 0);
 	this.statusErrorNoneRadioButton.setSelection(false);
@@ -749,18 +725,6 @@
 					int length = items.length;
 					for (int j=0; j<length; j++) {
 						if (items[j].equals(milestoneDate)) {
-							// already existing milestone, leave silently
-							if (MessageDialog.openQuestion(getShell(), getDialogTitle(), "Do you want to select milestone "+milestoneDate+" as the last build?")) {
-								String builds[] = this.lastBuildCombo.getItems();
-								int bLength = builds.length;
-								String milestone = milestoneDate.substring(milestoneDate.indexOf('-')+1);
-								for (int b=0; b<bLength; b++) {
-									if (builds[b].length() > 0 && Util.getBuildDate(builds[b]).equals(milestone)) {
-										this.lastBuildCombo.select(b);
-										break;
-									}
-								}
-							}
 							return;
 						}
 					}
@@ -817,8 +781,9 @@
 		String lastMilestone = length == 0 ? null : milestones[length-1];
 
 		// Verify that the added milestone is valid
-		final String databaseLocation = this.databaseLocationCombo.getText();
-		char version = databaseLocation.charAt(databaseLocation.length()-1);
+		char version = (char) ('0' + (this.mVersionRadioButton.getSelection()
+			? ECLIPSE_MAINTENANCE_VERSION
+			: ECLIPSE_DEVELOPMENT_VERSION) - 30);
 
 		// Verify that the milestone follow the last one
 		String milestoneName;
@@ -875,8 +840,8 @@
 	if (event.getSource() == this.statusBuildsToConfirm) {
 		try {
 			int number = Integer.parseInt(this.statusBuildsToConfirm.getText());
-			if (number < 1 ) {
-				this.statusBuildsToConfirm.setText("1");
+			if (number < 0) {
+				this.statusBuildsToConfirm.setText("0");
 			} else {
 				int buildsNumber = DB_Results.getBuildsNumber();
 				if (number > buildsNumber) {
@@ -1004,6 +969,11 @@
 	writeStatus += Integer.parseInt(this.statusBuildsToConfirm.getText());
 	store.setValue(PRE_WRITE_STATUS, writeStatus);
 
+	// Init comparison thresholds
+	store.setValue(PRE_COMPARISON_THRESHOLD_FAILURE, Integer.parseInt(this.comparisonThresholdFailure.getText()));
+	store.setValue(PRE_COMPARISON_THRESHOLD_ERROR, Integer.parseInt(this.comparisonThresholdError.getText()));
+	store.setValue(PRE_COMPARISON_THRESHOLD_IMPROVEMENT, Integer.parseInt(this.comparisonThresholdImprovement.getText()));
+
 	// Set milestones
 	String prefix = PRE_MILESTONE_BUILDS + "." + version;
 	count  = this.milestonesCombo.getItemCount();
@@ -1019,10 +989,6 @@
 		milestone = store.getString(prefix + count);
 	}
 
-	// Set last build
-	String lastBuild = this.lastBuildCombo.getText();
-	store.putValue(PRE_LAST_BUILD, lastBuild);
-
 	// Set default dimension
 	String defaultDimension = this.defaultDimensionCombo.getText();
 	store.putValue(PRE_DEFAULT_DIMENSION, defaultDimension);
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformancesView.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformancesView.java
index f9e8ca4..bd2d9bc 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformancesView.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/ui/PerformancesView.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
  * 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
@@ -20,9 +20,9 @@
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
 import org.eclipse.core.runtime.preferences.InstanceScope;
 import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
-import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.action.IMenuListener;
@@ -115,16 +115,6 @@
 	        return true;
         }
 	};
-	static String LAST_BUILD;
-	final static ViewerFilter FILTER_LAST_BUILDS = new ViewerFilter() {
-		public boolean select(Viewer v, Object parentElement, Object element) {
-			if (LAST_BUILD != null && element instanceof BuildResultsElement) {
-				BuildResultsElement buildElement = (BuildResultsElement) element;
-				return buildElement.isBefore(LAST_BUILD);
-			}
-	        return true;
-        }
-	};
 	Set viewFilters = new HashSet();
 
 	// SWT resources
@@ -133,8 +123,9 @@
 	TreeViewer viewer;
 	IPropertySheetPage propertyPage;
 
-	// Data info
+	// Directories
 	File dataDir;
+	File resultsDir = null;
 
 	// Views
 	IMemento viewState;
@@ -147,7 +138,6 @@
 	Action filterBaselineBuilds;
 	Action filterNightlyBuilds;
 	Action filterOldBuilds;
-	Action filterLastBuilds;
 //	Action dbConnection;
 
 	// Eclipse preferences
@@ -198,13 +188,9 @@
 
 	// Init milestones
 	Util.initMilestones(this.preferences);
-
-	// Init last build
-	String lastBuild = this.preferences.get(IPerformancesConstants.PRE_LAST_BUILD, null);
-	LAST_BUILD = lastBuild.length() == 0 ? null : lastBuild;
 }
 
-File changeDataDir() {
+File changeDataDir(String lastBuild) {
 	String localDataDir = this.preferences.get(IPerformancesConstants.PRE_LOCAL_DATA_DIR, "");
 	String filter = (this.dataDir == null) ? localDataDir : this.dataDir.getPath();
 	File dir = this.dataDir;
@@ -219,20 +205,13 @@
 		}
 		if (refresh) {
 			// Confirm the read when there's a last build set
-			if (LAST_BUILD != null) {
-				if (!MessageDialog.openConfirm(PerformancesView.this.shell, getTitleToolTip(), "Only builds before "+LAST_BUILD+" will be taken into account!\nDo you want to continue?")) {
+			if (lastBuild != null) {
+				if (!MessageDialog.openConfirm(PerformancesView.this.shell, getTitleToolTip(), "Only builds before "+lastBuild+" will be taken into account!\nDo you want to continue?")) {
 					return null;
 				}
 			}
-
-			// Read local files
-			readLocalFiles();
-
-			// Refresh views
-			refreshInput();
-			PerformancesView resultsView = getSiblingView();
-			resultsView.refreshInput();
-			return resultsView.dataDir = this.dataDir;
+			refresh(lastBuild);
+			return getSiblingView().dataDir = this.dataDir;
 		}
 	}
 	return null;
@@ -323,19 +302,6 @@
 }
 
 /*
- * Filter non fingerprints scenarios action run.
- */
-void filterLastBuilds(boolean filter, boolean updatePreference) {
-	if (filter) {
-		this.viewFilters.add(FILTER_LAST_BUILDS);
-	} else {
-		this.viewFilters.remove(FILTER_LAST_BUILDS);
-	}
-	this.preferences.putBoolean(IPerformancesConstants.PRE_FILTER_LAST_BUILDS, filter);
-	updateFilters();
-}
-
-/*
  * Filter non milestone builds action run.
  */
 void filterNightlyBuilds(boolean filter, boolean updatePreference) {
@@ -437,7 +403,7 @@
 			File dir = new File(localDataDir);
 			if (dir.exists() && dir.isDirectory()) {
 				this.dataDir = dir;
-				readLocalFiles();
+				readLocalFiles(null);
 			}
 		}
 	}
@@ -451,7 +417,7 @@
 	// Change data dir action
 	this.changeDataDir = new Action("&Read...") {
 		public void run() {
-			changeDataDir();
+			changeDataDir(null);
 		}
 	};
 	this.changeDataDir.setToolTipText("Change the directory of the local data files");
@@ -486,79 +452,26 @@
 	};
 	this.filterOldBuilds.setChecked(false);
 	this.filterOldBuilds.setToolTipText("Filter old builds (i.e. before last milestone) but keep all previous milestones)");
-
-	// Filter non-important builds action
-	this.filterLastBuilds = new Action("&Last Builds", IAction.AS_CHECK_BOX) {
-		public void run() {
-			filterLastBuilds(isChecked(), true/*update preference*/);
-		}
-	};
-	final String lastBuild = this.preferences.get(IPerformancesConstants.PRE_LAST_BUILD, null);
-	this.filterLastBuilds.setChecked(false);
-	if (lastBuild == null) {
-		this.filterLastBuilds.setEnabled(false);
-	} else {
-		this.filterLastBuilds.setToolTipText("Filter last builds (i.e. after "+lastBuild+" build)");
-	}
 }
 
 /* (non-Javadoc)
  * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent)
  */
 public void preferenceChange(PreferenceChangeEvent event) {
-	String propertyName = event.getKey();
-//	String newValue = (String) event.getNewValue();
-
-	// Eclipse version change
-	if (propertyName.equals(IPerformancesConstants.PRE_ECLIPSE_VERSION)) {
-//		int eclipseVersion = newValue == null ? IPerformancesConstants.DEFAULT_ECLIPSE_VERSION : Integer.parseInt(newValue);
-//		String databaseLocation = this.preferences.get(IPerformancesConstants.PRE_DATABASE_LOCATION, IPerformancesConstants.NETWORK_DATABASE_LOCATION);
-//		boolean connected = this.preferences.getBoolean(IPerformancesConstants.PRE_DATABASE_CONNECTION, IPerformancesConstants.DEFAULT_DATABASE_CONNECTION);
-//		DB_Results.updateDbConstants(connected, eclipseVersion, databaseLocation);
-//		setTitleToolTip();
-	}
-
-	// Database location change
-	if (propertyName.equals(IPerformancesConstants.PRE_DATABASE_LOCATION)) {
-//		boolean connected = this.preferences.getBoolean(IPerformancesConstants.PRE_DATABASE_CONNECTION, IPerformancesConstants.DEFAULT_DATABASE_CONNECTION);
-//		int eclipseVersion = this.preferences.getInt(IPerformancesConstants.PRE_ECLIPSE_VERSION, IPerformancesConstants.DEFAULT_ECLIPSE_VERSION);
-//		DB_Results.updateDbConstants(connected, eclipseVersion, newValue);
-//		setTitleToolTip();
-	}
-
-	// Database connection
-	if (propertyName.equals(IPerformancesConstants.PRE_DATABASE_CONNECTION)) {
-//		boolean connected = newValue == null ? IPerformancesConstants.DEFAULT_DATABASE_CONNECTION : newValue.equals(Boolean.TRUE);
-//		int eclipseVersion = this.preferences.getInt(IPerformancesConstants.PRE_ECLIPSE_VERSION, IPerformancesConstants.DEFAULT_ECLIPSE_VERSION);
-//		String databaseLocation = this.preferences.get(IPerformancesConstants.PRE_DATABASE_LOCATION, IPerformancesConstants.NETWORK_DATABASE_LOCATION);
-//		DB_Results.updateDbConstants(connected, eclipseVersion, databaseLocation);
-//		setTitleToolTip();
-	}
-
-	// Last build
-	if (propertyName.equals(IPerformancesConstants.PRE_LAST_BUILD)) {
-//		if (newValue == null || newValue.length() == 0) {
-//			this.filterLastBuilds.setEnabled(false);
-//			LAST_BUILD = null;
-//		} else {
-//			this.filterLastBuilds.setEnabled(true);
-//			this.filterLastBuilds.setToolTipText("Filter last builds (i.e. after "+newValue+" build)");
-//			LAST_BUILD = newValue;
-//		}
-	}
+	// do nothing
 }
 
 /*
  * Read local files
  */
-void readLocalFiles() {
+void readLocalFiles(final String lastBuild) {
 
 	// Create runnable to read local files
 	IRunnableWithProgress runnable = new IRunnableWithProgress() {
 		public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
 			try {
 				monitor.beginTask("Read local files", 1000);
-				PerformancesView.this.results.readLocal(PerformancesView.this.dataDir, monitor, LAST_BUILD);
+				PerformancesView.this.results.readLocal(PerformancesView.this.dataDir, monitor, lastBuild);
 				monitor.done();
 			} catch (Exception e) {
 				e.printStackTrace();
@@ -578,6 +491,19 @@
 }
 
 /*
+ * Refresh the views.
+ */
+void refresh(String lastBuild) {
+
+	// Read local files
+	readLocalFiles(lastBuild);
+
+	// Refresh views
+	refreshInput();
+	getSiblingView().refreshInput();
+}
+
+/*
  * Refresh the entire view by resetting its input.
  */
 void refreshInput() {
@@ -607,6 +533,10 @@
 		if (filterBaselinesValue) {
 			this.viewFilters.add(FILTER_BASELINE_BUILDS);
 		}
+		String dir = this.viewState.getString(IPerformancesConstants.PRE_WRITE_RESULTS_DIR);
+		if (dir != null) {
+			this.resultsDir = new File(dir);
+		}
 	}
 
 	// Filter nightly builds action
@@ -622,13 +552,6 @@
 	if (checked) {
 		this.viewFilters.add(FILTER_OLD_BUILDS);
 	}
-
-	// Filter last builds action state
-	checked = this.preferences.getBoolean(IPerformancesConstants.PRE_FILTER_LAST_BUILDS, IPerformancesConstants.DEFAULT_FILTER_LAST_BUILDS);
-	this.filterLastBuilds.setChecked(checked);
-	if (checked) {
-		this.viewFilters.add(FILTER_LAST_BUILDS);
-	}
 }
 
 public void saveState(IMemento memento) {
@@ -639,6 +562,9 @@
 	} catch (BackingStoreException e) {
 		// ignore
 	}
+	if (this.resultsDir != null) {
+		memento.putString(IPerformancesConstants.PRE_WRITE_RESULTS_DIR, this.resultsDir.getPath());
+	}
 }
 
 /*
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/utils/IPerformancesConstants.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/utils/IPerformancesConstants.java
index 7c15295..4891202 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/utils/IPerformancesConstants.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/utils/IPerformancesConstants.java
@@ -32,7 +32,6 @@
     public static final String PRE_RESULTS_GENERATION_DIR = PREFIX + "results.generation.dir"; //$NON-NLS-1$
     public static final String PRE_CONFIG_DESCRIPTOR_NAME = PREFIX + "config.descriptor.name"; //$NON-NLS-1$
     public static final String PRE_CONFIG_DESCRIPTOR_DESCRIPTION = PREFIX + "config.descriptor.description"; //$NON-NLS-1$
-    public static final String PRE_LAST_BUILD = PREFIX + "last.build"; //$NON-NLS-1$
     public static final String PRE_DEFAULT_DIMENSION = PREFIX + "default.dimension"; //$NON-NLS-1$
     public static final String PRE_RESULTS_DIMENSION = PREFIX + "results.dimension"; //$NON-NLS-1$
     public static final String PRE_MILESTONE_BUILDS = PREFIX + "milestone.builds"; //$NON-NLS-1$
@@ -40,19 +39,17 @@
     public static final String PRE_FILTER_ADVANCED_SCENARIOS = PREFIX + "filter.non.fingerprints.scenarios"; //$NON-NLS-1$
     public static final String PRE_FILTER_OLD_BUILDS = PREFIX + "filter.non.milestones.builds"; //$NON-NLS-1$
     public static final String PRE_FILTER_NIGHTLY_BUILDS = PREFIX + "filter.nightly.builds"; //$NON-NLS-1$
-    public static final String PRE_FILTER_LAST_BUILDS = PREFIX + "filter.last.builds"; //$NON-NLS-1$
 
 	// Other constants
-	public static final int ECLIPSE_MAINTENANCE_VERSION = 35;
-	public static final int ECLIPSE_DEVELOPMENT_VERSION = 36;
+	public static final int ECLIPSE_MAINTENANCE_VERSION = 36;
+	public static final int ECLIPSE_DEVELOPMENT_VERSION = 37;
 
 	// Default values
 	public static final String DATABASE_NAME_PREFIX = "perfDb";
-	public static final String NETWORK_DATABASE_LOCATION = "net://trelenggtk.ottawa.ibm.com:1528";
+	public static final String NETWORK_DATABASE_LOCATION = "net://minsky.ottawa.ibm.com:1528";
 	public static final int DEFAULT_ECLIPSE_VERSION = ECLIPSE_DEVELOPMENT_VERSION;
 	public static final boolean DEFAULT_FILTER_ADVANCED_SCENARIOS = true;
 	public static final boolean DEFAULT_FILTER_OLD_BUILDS = false;
-	public static final boolean DEFAULT_FILTER_LAST_BUILDS = false;
 	public static final boolean DEFAULT_FILTER_NIGHTLY_BUILDS = false;
 	public static final boolean DEFAULT_DATABASE_CONNECTION = false;
 	public static final boolean DEFAULT_DATABASE_LOCAL = false;
@@ -76,7 +73,17 @@
 	public static final int STATUS_STATISTICS_MASK = 0xC000;
 	public static final int DEFAULT_WRITE_STATUS = STATUS_ERROR_NONE | DEFAULT_BUILDS_NUMBER;
 
+	// Comparison
+    public static final String PRE_COMPARISON_THRESHOLD_FAILURE = PREFIX + "comparison.threshold.failure"; //$NON-NLS-1$
+	public static final int DEFAULT_COMPARISON_THRESHOLD_FAILURE = 10;
+    public static final String PRE_COMPARISON_THRESHOLD_ERROR = PREFIX + "comparison.threshold.error"; //$NON-NLS-1$
+	public static final int DEFAULT_COMPARISON_THRESHOLD_ERROR = 3;
+    public static final String PRE_COMPARISON_THRESHOLD_IMPROVEMENT = PREFIX + "comparison.threshold.imporvement"; //$NON-NLS-1$
+	public static final int DEFAULT_COMPARISON_THRESHOLD_IMPROVEMENT = 10;
+
 	// Default milestones nowadays
+	public static final String[] V37_MILESTONES = new String[] {
+	};
 	public static final String[] V36_MILESTONES = new String[] {
 		"M1-200908060100",
 		"M2-200909170100",
@@ -85,6 +92,7 @@
 		"M5-201001291300",
 		"M6-201003121448",
 	};
+	/** @deprecated */
 	public static final String[] V35_MILESTONES = new String[] {
 		        "M1-200808071402",
 		        "M2-200809180100",
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/utils/Util.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/utils/Util.java
index 5199381..4bddd41 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/utils/Util.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/utils/Util.java
@@ -78,6 +78,9 @@
 	private static String[] MILESTONES;
 	public static final BuildDateComparator BUILD_DATE_COMPARATOR = new BuildDateComparator();
 
+	// Components constants
+	public static final String ORG_ECLIPSE = "org.eclipse.";
+
 static class BuildDateComparator implements Comparator {
 	public int compare(Object o1, Object o2) {
 		String s1 = (String) o1;
@@ -98,13 +101,14 @@
 		switch (minorVersion) {
 			case '3':
 			case '4':
-				throw new RuntimeException("Version "+mainVersion+'.'+minorVersion+" is no longer supported!");
 			case '5':
-				MILESTONES = V35_MILESTONES;
-				break;
+				throw new RuntimeException("Version "+mainVersion+'.'+minorVersion+" is no longer supported!");
 			case '6':
 				MILESTONES = V36_MILESTONES;
 				break;
+			case '7':
+				MILESTONES = V37_MILESTONES;
+				break;
 			default:
 				throw new RuntimeException("Version "+mainVersion+'.'+minorVersion+" is not supported yet!");
 		}
@@ -119,6 +123,84 @@
 public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmm"); //$NON-NLS-1$
 
 /**
+ * Return the name to display for the given component.
+ * <p>
+ * This name is built from the name of the component selected in the Components view.
+ * The rules to build the name are:
+ * <ol>
+ * <li>If the component name does not start with "org.eclipse" then the part name is just
+ * 		"<b>component name</b>"</li>
+ * <li>Otherwise, remove "org.eclipse." form the component name and count
+ * 		the tokens separated by a dot ('.')
+ * 		<ul>
+ * 		<li>If there's only one remaining token, then the part name is "<b>Platform/</b>"
+ * 			followed by:
+ * 			<ul>
+ * 			<li>"<b><i>TOKEN</i></b>" if token is less than 3 characters,</li>
+ * 			<li>"<b><i>Token</i></b>" otherwise</li>
+ * 			</ul>
+ * 		</li>
+ * 		<li>Otherwise then the part name is "<b><i>FIRST_TOKEN</i></b>" followed by:
+ * 			<ul>
+ * 			<li>for each followed additional token:
+ * 				<ul>
+ * 				<li>"<b><i>TOKEN</i></b>" if token is less than 3 characters,</li>
+ * 				<li>"<b><i>Token</i></b>" otherwise</li>
+ * 				</ul>
+ * 			</li>
+ * 			</ul>
+ * 		</li>
+ * 		</ul>
+ * </ol>
+ * E.g.
+ * 	- org.eclipse.ui -> "Platform/UI"
+ * 	- org.eclipse.swt -> "Platform/SWT"
+ * 	- org.eclipse.team -> "Platform/Team"
+ * 	- org.eclipse.jdt.ui -> "JDT/UI"
+ * 	- org.eclipse.jdt.core -> "JDT/Core"
+ * 	- org.eclipse.pde.api.tools -> "PDE/API Tools"
+ */
+public static String componentDisplayName(String componentName) {
+	String partName;
+	StringBuffer buffer = null;
+	if (componentName.startsWith(ORG_ECLIPSE)) {
+		partName = componentName.substring(ORG_ECLIPSE.length());
+		StringTokenizer tokenizer = new StringTokenizer(partName, ".");
+		while (tokenizer.hasMoreTokens()) {
+			String token = tokenizer.nextToken();
+			if (buffer == null) {
+				if (tokenizer.hasMoreTokens()) {
+					buffer = new StringBuffer("'"+token.toUpperCase());
+					buffer.append('/');
+				} else {
+					buffer = new StringBuffer("'Platform/");
+					if (token.length() > 3) {
+						buffer.append(Character.toUpperCase(token.charAt(0)));
+						buffer.append(token.substring(1));
+					} else {
+						buffer.append(token.toUpperCase());
+					}
+				}
+			} else {
+				if (token.length() > 3) {
+					buffer.append(Character.toUpperCase(token.charAt(0)));
+					buffer.append(token.substring(1));
+				} else {
+					buffer.append(token.toUpperCase());
+				}
+				if (tokenizer.hasMoreTokens()) buffer.append(' ');
+			}
+		}
+	} else {
+		buffer = new StringBuffer("'");
+		buffer.append(componentName);
+		buffer.append("'");
+	}
+	buffer.append("' results");
+	return buffer.toString();
+}
+
+/**
  * Compute the student t-test values.
  *
  * @see "http://en.wikipedia.org/wiki/Student's_t-test"
@@ -526,7 +608,7 @@
 /**
  * Set the milestones.
  *
- * @param items The milestones list (e.g. {@link IPerformancesConstants#V35_MILESTONES}).
+ * @param items The milestones list (e.g. {@link IPerformancesConstants#V37_MILESTONES}).
  */
 public static void setMilestones(String[] items) {
 	MILESTONES = items;
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/GenerateResults.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/GenerateResults.java
index 0a283c6..b225af7 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/GenerateResults.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/GenerateResults.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2010 IBM Corporation and others.
  * 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
@@ -29,7 +29,6 @@
 import org.eclipse.core.runtime.SubMonitor;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.test.internal.performance.results.db.ConfigResults;
-import org.eclipse.test.internal.performance.results.db.DB_Results;
 import org.eclipse.test.internal.performance.results.db.PerformanceResults;
 import org.eclipse.test.internal.performance.results.db.ScenarioResults;
 import org.eclipse.test.internal.performance.results.utils.Util;
@@ -186,14 +185,11 @@
 public GenerateResults() {
 }
 
-public GenerateResults(PerformanceResults results, String current, String baseline, boolean fingerprints, File data, File output) {
+public GenerateResults(boolean fingerprints, File data) {
 	this.dataDir = data;
-	this.outputDir = output;
 	this.genFingerPrints = fingerprints;
 	this.genAll = !fingerprints;
-	this.performanceResults = results;
 	this.printStream = System.out;
-	setDefaults(current, baseline);
 }
 
 /*
@@ -825,17 +821,24 @@
  */
 public IStatus run(String[] args) {
 	parse(args);
-	return run((IProgressMonitor) null);
+	return generate(null);
 }
 
 /**
- * Run the generation using a progress monitor.
+ * Run the generation.
+ */
+public IStatus run(PerformanceResults results, String buildName, String baseline, File output, final IProgressMonitor monitor) {
+	this.performanceResults = results;
+	this.outputDir = output;
+	setDefaults(buildName, baseline);
+	return generate(monitor);
+}
+
+/*
  * Note that all necessary information to generate properly must be set before
  * calling this method
- *
- * @see #run(String[])
  */
-public IStatus run(final IProgressMonitor monitor) {
+private IStatus generate(final IProgressMonitor monitor) {
 	long begin = System.currentTimeMillis();
 	int work = 1100;
     int dataWork = 1000 * this.performanceResults.getConfigBoxes(false).length;
@@ -843,6 +846,7 @@
 	    work += dataWork;
     }
 	SubMonitor subMonitor = SubMonitor.convert(monitor, work);
+	subMonitor.setTaskName("Generate perf results for build "+this.performanceResults.getName());
 	try {
 
 		// Print whole scenarios summary
@@ -914,8 +918,9 @@
 			this.printStream.print("	- components main page");
 		}
 		long start = System.currentTimeMillis();
-		subMonitor.setTaskName("Write fingerprints: 0%");
-		subMonitor.subTask("Global...");
+//		subMonitor.setTaskName("Write fingerprints: 0%");
+//		subMonitor.subTask("Global...");
+		subMonitor.subTask("Write fingerprints: global (0%)...");
 		printComponent(/*performanceResults, */"global_fp");
 		subMonitor.worked(100);
 		if (subMonitor.isCanceled()) throw new OperationCanceledException();
@@ -925,8 +930,9 @@
 		int progress = 0;
 		for (int i=0; i<length; i++) {
 			int percentage = (int) ((progress / ((double) length)) * 100);
-			subMonitor.setTaskName("Write fingerprints: "+percentage+"%");
-			subMonitor.subTask(components[i]+"...");
+//			subMonitor.setTaskName("Write fingerprints: "+percentage+"%");
+//			subMonitor.subTask(components[i]+"...");
+			subMonitor.subTask("Write fingerprints: "+components[i]+" ("+percentage+"%)...");
 			printComponent(/*performanceResults, */components[i]);
 			subMonitor.worked(step);
 			if (subMonitor.isCanceled()) throw new OperationCanceledException();
@@ -1012,7 +1018,8 @@
 		if (index > 0) {
 			this.baselinePrefix = baseline.substring(0, index);
 		} else {
-			this.baselinePrefix = DB_Results.getDbBaselinePrefix();
+//			this.baselinePrefix = DB_Results.getDbBaselinePrefix();
+			this.baselinePrefix = baseline;
 		}
 	}
 
diff --git a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioData.java b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioData.java
index 9278a1c..3cb5a78 100644
--- a/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioData.java
+++ b/bundles/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/ScenarioData.java
@@ -170,7 +170,9 @@
 		final String configBox = configBoxes[i];
 
 		// Manage monitor
-		subMonitor.setTaskName("Generating data for "+configBox);
+//		subMonitor.setTaskName("Generating data for "+configBox);
+		final String subTaskPrefix = "Generating data: "+configBox;
+		subMonitor.subTask(subTaskPrefix);
 		if (subMonitor.isCanceled()) throw new OperationCanceledException();
 
 		long start = System.currentTimeMillis();
@@ -184,8 +186,9 @@
 
 			// Manage monitor
 			int percentage = (int) ((progress++ / total) * 100);
-			subMonitor.setTaskName("Generating data for "+configBox+": "+percentage+"%");
-			subMonitor.subTask("Component "+componentResults.getName()+"...");
+//			subMonitor.setTaskName("Generating data for "+configBox+": "+percentage+"%");
+//			subMonitor.subTask("Component "+componentResults.getName()+"...");
+			subMonitor.subTask(subTaskPrefix + " (" +componentResults.getName()+ ") "+ percentage + "%...");
 
 			Display display = Display.getDefault();
 		     display.syncExec(
diff --git a/bundles/org.eclipse.test.performance.ui/toc.xml b/bundles/org.eclipse.test.performance.ui/toc.xml
index 864ff8a..32d0d3f 100644
--- a/bundles/org.eclipse.test.performance.ui/toc.xml
+++ b/bundles/org.eclipse.test.performance.ui/toc.xml
@@ -10,7 +10,8 @@
 		<topic label="Components" href="html/components.html"/> 
 		<topic label="Properties" href="html/properties.html"/> 
 		<topic label="Builds" href="html/builds.html"/> 
-		<topic label="Results" href="html/results.html"/> 
+		<topic label="Results" href="html/results.html"/>
+		<topic href="html/builds-comparison.html" label="Builds Comparison"/>
 	</topic>
 	<topic label="Verification" href="html/verification.html"/> 
 </toc>