diff options
Diffstat (limited to 'basebuilder-3.6.2/org.eclipse.releng.basebuilder/plugins/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/GenerateResults.java')
-rw-r--r-- | basebuilder-3.6.2/org.eclipse.releng.basebuilder/plugins/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/GenerateResults.java | 1050 |
1 files changed, 1050 insertions, 0 deletions
diff --git a/basebuilder-3.6.2/org.eclipse.releng.basebuilder/plugins/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/GenerateResults.java b/basebuilder-3.6.2/org.eclipse.releng.basebuilder/plugins/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/GenerateResults.java new file mode 100644 index 0000000..0a283c6 --- /dev/null +++ b/basebuilder-3.6.2/org.eclipse.releng.basebuilder/plugins/org.eclipse.test.performance.ui/src/org/eclipse/test/performance/ui/GenerateResults.java @@ -0,0 +1,1050 @@ +/******************************************************************************* + * 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.performance.ui; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.StringTokenizer; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +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; +import org.osgi.framework.Bundle; + +/** + * Main class to generate performance results of all scenarios matching a given pattern + * in one HTML page per component. + * + * @see #printUsage() method to see a detailed parameters usage + */ +public class GenerateResults { + +/** + * Prefix of baseline builds displayed in data graphs. + * This field is set using <b>-baseline.prefix</b> argument. + * <p> + * Example: + * <pre>-baseline.prefix 3.2_200606291905</pre> + * + * @see #currentBuildPrefixes + */ +String baselinePrefix = null; + +/** + * Root directory where all files are generated. + * This field is set using <b>-output</b> argument. + * <p> + * Example: + * <pre>-output /releng/results/I20070615-1200/performance</pre> + */ +File outputDir; + +/** + * Root directory where all data are locally stored to speed-up generation. + * This field is set using <b>-dataDir</b> argument. + * <p> + * Example: + * <pre>-dataDir /tmp</pre> + */ +File dataDir; + +/** + * Arrays of 2 strings which contains config information: name and description. + * This field is set using <b>-config</b> and/or <b>-config.properties</b> arguments. + * <p> + * Example: + * <pre> + * -config eclipseperflnx3_R3.3,eclipseperfwin2_R3.3,eclipseperflnx2_R3.3,eclipseperfwin1_R3.3,eclipseperflnx1_R3.3 + * -config.properties + * "eclipseperfwin1_R3.3,Win XP Sun 1.4.2_08 (2 GHz 512 MB); + * eclipseperflnx1_R3.3,RHEL 3.0 Sun 1.4.2_08 (2 GHz 512 MB); + * eclipseperfwin2_R3.3,Win XP Sun 1.4.2_08 (3 GHz 2 GB); + * eclipseperflnx2_R3.3,RHEL 3.0 Sun 1.4.2_08 (3 GHz 2 GB); + * eclipseperflnx3_R3.3,RHEL 4.0 Sun 1.4.2_08 (3 GHz 2.5 GB)" + * </pre> + * Note that: + * <ul> + * <li>if only <b>-config</b> is set, then configuration name is used for description </li> + * <li>if only <b>-config.properties</b> is set, then all configurations defined with this argument are generated + * <li>if both arguments are defined, then only configurations defined by <b>-config</b> argument are generated, + * <b>-config.properties</b> argument is only used to set the configuration description.</li> + * </ul> + */ +String[][] configDescriptors; + +/** + * Scenario pattern used to generate performance results. + * This field is set using <b>-scenarioPattern</b> argument. + * <p> + * Note that this pattern uses SQL conventions, not RegEx ones, + * which means that '%' is used to match several consecutive characters + * and '_' to match a single character. + * <p> + * Example: + * <pre>-scenario.pattern org.eclipse.%.test</pre> + */ +String scenarioPattern; + +/** + * A list of prefixes for builds displayed in data graphs. + * This field is set using <b>-currentPrefix</b> argument. + * <p> + * Example: + * <pre>-current.prefix N, I</pre> + * + * @see #baselinePrefix + */ +List currentBuildPrefixes; + +/** + * A list of prefixes of builds to highlight in displayed data graphs. + * This field is set using <b>-highlight</b> and/or <b>-highlight.latest</b> arguments. + * <p> + * Example: + * <pre>-higlight 3_2</pre> + */ +List pointsOfInterest; + +/** + * Tells whether only fingerprints has to be generated. + * This field is set to <code>true</code> if <b>-fingerprints</b> argument is specified. + * <p> + * Default is <code>false</code> which means that scenario data + * will also be generated. + * + * @see #genData + * @see #genAll + */ +boolean genFingerPrints = false; + +/** + * Tells whether only fingerprints has to be generated. + * This field is set to <code>true</code> if <b>-data</b> argument is specified. + * <p> + * Default is <code>false</code> which means that fingerprints + * will also be generated. + * + * @see #genFingerPrints + * @see #genAll + */ +boolean genData = false; + +/** + * Tells whether only fingerprints has to be generated. + * This field is set to <code>false</code> + * if <b>-fingerprints</b> or <b>-data</b> argument is specified. + * <p> + * Default is <code>true</code> which means that scenario data + * will also be generated. + * + * @see #genData + * @see #genFingerPrints + */ +boolean genAll = true; + +/** + * Tells whether information should be displayed in the console while generating. + * This field is set to <code>true</code> if <b>-print</b> argument is specified. + * <p> + * Default is <code>false</code> which means that nothing is print during the generation. + */ +PrintStream printStream = null; + +/** + * Tells what should be the failure percentage threshold. + * <p> + * Default is 10%. + */ +int failure_threshold = 10; // PerformanceTestPlugin.getDBLocation().startsWith("net://"); + +PerformanceResults performanceResults; + +public GenerateResults() { +} + +public GenerateResults(PerformanceResults results, String current, String baseline, boolean fingerprints, File data, File output) { + this.dataDir = data; + this.outputDir = output; + this.genFingerPrints = fingerprints; + this.genAll = !fingerprints; + this.performanceResults = results; + this.printStream = System.out; + setDefaults(current, baseline); +} + +/* + * Parse the command arguments and create corresponding performance + * results object. + */ +private void parse(String[] args) { + StringBuffer buffer = new StringBuffer("Parameters used to generate performance results ("); + buffer.append(new SimpleDateFormat().format(new Date(System.currentTimeMillis()))); + buffer.append("):\n"); + int i = 0; + int argsLength = args.length; + if (argsLength == 0) { + printUsage(); + } + + String currentBuildId = null; + String baseline = null; + String jvm = null; + this.configDescriptors = null; + + while (i < argsLength) { + String arg = args[i]; + if (!arg.startsWith("-")) { + i++; + continue; + } + if (argsLength == i + 1 && i != argsLength - 1) { + System.out.println("Missing value for last parameter"); + printUsage(); + } + if (arg.equals("-baseline")) { + baseline = args[i + 1]; + if (baseline.startsWith("-")) { + System.out.println("Missing value for "+arg+" parameter"); + printUsage(); + } + buffer.append(" -baseline = "+baseline+'\n'); + i++; + continue; + } + if (arg.equals("-baseline.prefix")) { + this.baselinePrefix = args[i + 1]; + if (this.baselinePrefix.startsWith("-")) { + System.out.println("Missing value for "+arg+" parameter"); + printUsage(); + } + buffer.append(" ").append(arg).append(" = ").append(this.baselinePrefix).append('\n'); + i++; + continue; + } + if (arg.equals("-current.prefix")) { + String idPrefixList = args[i + 1]; + if (idPrefixList.startsWith("-")) { + System.out.println("Missing value for "+arg+" parameter"); + printUsage(); + } + buffer.append(" ").append(arg).append(" = "); + String[] ids = idPrefixList.split(","); + this.currentBuildPrefixes = new ArrayList(); + for (int j = 0; j < ids.length; j++) { + this.currentBuildPrefixes.add(ids[j]); + buffer.append(ids[j]); + } + buffer.append('\n'); + i++; + continue; + } + if (arg.equals("-highlight") || arg.equals("-highlight.latest")) { + if (args[i + 1].startsWith("-")) { + System.out.println("Missing value for "+arg+" parameter"); + printUsage(); + } + buffer.append(" ").append(arg).append(" = "); + String[] ids = args[i + 1].split(","); + this.pointsOfInterest = new ArrayList(); + for (int j = 0; j < ids.length; j++) { + this.pointsOfInterest.add(ids[j]); + buffer.append(ids[j]); + } + buffer.append('\n'); + i++; + continue; + } + if (arg.equals("-current")) { + currentBuildId = args[i + 1]; + if (currentBuildId.startsWith("-")) { + System.out.println("Missing value for "+arg+" parameter"); + printUsage(); + } + buffer.append(" ").append(arg).append(" = ").append(currentBuildId).append('\n'); + i++; + continue; + } + if (arg.equals("-jvm")) { + jvm = args[i + 1]; + if (jvm.startsWith("-")) { + System.out.println("Missing value for "+arg+" parameter"); + printUsage(); + } + buffer.append(" ").append(arg).append(" = ").append(jvm).append('\n'); + i++; + continue; + } + if (arg.equals("-output")) { + String dir = args[++i]; + if (dir.startsWith("-")) { + System.out.println("Missing value for "+arg+" parameter"); + printUsage(); + } + this.outputDir = new File(dir); + if (!this.outputDir.exists() && !this.outputDir.mkdirs()) { + System.err.println("Cannot create directory "+dir+" to write results in!"); + System.exit(2); + } + buffer.append(" ").append(arg).append(" = ").append(dir).append('\n'); + continue; + } + if (arg.equals("-dataDir")) { + String dir = args[++i]; + if (dir.startsWith("-")) { + System.out.println("Missing value for "+arg+" parameter"); + printUsage(); + } + this.dataDir = new File(dir); + if (!this.dataDir.exists() && !this.dataDir.mkdirs()) { + System.err.println("Cannot create directory "+dir+" to save data locally!"); + System.exit(2); + } + buffer.append(" ").append(arg).append(" = ").append(dir).append('\n'); + continue; + } + if (arg.equals("-config")) { + String configs = args[i + 1]; + if (configs.startsWith("-")) { + System.out.println("Missing value for "+arg+" parameter"); + printUsage(); + } + String[] names = configs.split(","); + int length = names.length; + buffer.append(" ").append(arg).append(" = "); + for (int j=0; j<length; j++) { + if (j>0) buffer.append(','); + buffer.append(names[j]); + } + if (this.configDescriptors == null) { + this.configDescriptors = new String[length][2]; + for (int j=0; j<length; j++) { + this.configDescriptors[j][0] = names[j]; + this.configDescriptors[j][1] = names[j]; + } + } else { + int confLength = this.configDescriptors[0].length; + int newLength = confLength; + mainLoop: for (int j=0; j<confLength; j++) { + for (int k=0; k<length; k++) { + if (this.configDescriptors[j][0].equals(names[k])) { + continue mainLoop; + } + } + this.configDescriptors[j][0] = null; + this.configDescriptors[j][1] = null; + newLength--; + } + if (newLength < confLength) { + String[][] newDescriptors = new String[newLength][2]; + for (int j=0, c=0; j<newLength; j++) { + if (this.configDescriptors[c] != null) { + newDescriptors[j][0] = this.configDescriptors[c][0]; + newDescriptors[j][1] = this.configDescriptors[c][1]; + } else { + c++; + } + } + this.configDescriptors = newDescriptors; + } + } + buffer.append('\n'); + i++; + continue; + } + if (arg.equals("-config.properties")) { + String configProperties = args[i + 1]; + if (configProperties.startsWith("-")) { + System.out.println("Missing value for "+arg+" parameter"); + printUsage(); + } + if (this.configDescriptors == null) { + System.out.println("Missing -config parameter"); + printUsage(); + } + int length = this.configDescriptors.length; + StringTokenizer tokenizer = new StringTokenizer(configProperties, ";"); + buffer.append('\t').append(arg).append(" = '").append(configProperties).append("' splitted in ").append(length).append(" configs:"); + while (tokenizer.hasMoreTokens()) { + String labelDescriptor = tokenizer.nextToken(); + String[] elements = labelDescriptor.trim().split(","); + for (int j=0; j<length; j++) { + if (elements[0].equals(this.configDescriptors[j][0])) { + this.configDescriptors[j][1] = elements[1]; + buffer.append("\n\t\t+ "); + buffer.append(elements[0]); + buffer.append(" -> "); + buffer.append(elements[1]); + } + } + } + buffer.append('\n'); + i++; + continue; + } + if (arg.equals("-scenario.filter") || arg.equals("-scenario.pattern")) { + this.scenarioPattern= args[i + 1]; + if (this.scenarioPattern.startsWith("-")) { + System.out.println("Missing value for "+arg+" parameter"); + printUsage(); + } + buffer.append(" ").append(arg).append(" = ").append(this.scenarioPattern).append('\n'); + i++; + continue; + } + if (arg.equals("-fingerprints")) { + this.genFingerPrints = true; + this.genAll = false; + buffer.append(" ").append(arg).append('\n'); + i++; + continue; + } + if (arg.equals("-data")) { + this.genData = true; + this.genAll = false; + buffer.append(" ").append(arg).append('\n'); + i++; + continue; + } + if (arg.equals("-print")) { + this.printStream = System.out; // default is to print to console + buffer.append(" ").append(arg); + i++; + String printFile = i==argsLength ? null : args[i]; + if (printFile==null ||printFile.startsWith("-")) { + buffer.append(" (to the console)").append('\n'); + } else { + try { + this.printStream = new PrintStream(new BufferedOutputStream(new FileOutputStream(printFile))); + } + catch (FileNotFoundException fnfe) { + // use the console if the output file cannot be created + } + buffer.append(" (to file: ").append(printFile).append(")\n"); + } + continue; + } + if (arg.equals("-failure.threshold")) { + String value = args[i + 1]; + try { + this.failure_threshold = Integer.parseInt(value); + if (this.failure_threshold < 0) { + System.out.println("Value for "+arg+" parameter must be positive."); + printUsage(); + } + } + catch (NumberFormatException nfe) { + System.out.println("Invalid value for "+arg+" parameter"); + printUsage(); + } + buffer.append(" ").append(arg).append(" = ").append(value).append('\n'); + i++; + continue; + } + i++; + } + if (this.printStream != null) { + this.printStream.print(buffer.toString()); + } + + // Stop if some mandatory parameters are missing + if (this.outputDir == null || this.configDescriptors == null || jvm == null) { + printUsage(); + } + + // Set performance results + setPerformanceResults(currentBuildId, baseline); +} + +/* + * Print component PHP file + */ +private void printComponent(/*PerformanceResults performanceResults, */String component) throws FileNotFoundException { + if (this.printStream != null) this.printStream.print("."); + File outputFile = new File(this.outputDir, component + ".php"); + PrintStream stream = new PrintStream(new BufferedOutputStream(new FileOutputStream(outputFile))); + + // Print header + boolean isGlobal = component.startsWith("global"); + if (isGlobal) { + File globalFile = new File(this.outputDir, "global.php"); + PrintStream gStream = new PrintStream(new BufferedOutputStream(new FileOutputStream(globalFile))); + gStream.print(Utils.HTML_OPEN); + gStream.print("</head>\n"); + gStream.print("<body>\n"); + gStream.print("<?php\n"); + gStream.print(" include(\"global_fp.php\");\n"); + gStream.print("?>\n"); + gStream.print("<table border=0 cellpadding=2 cellspacing=5 width=\"100%\">\n"); + gStream.print("<tbody><tr> <td colspan=3 align=\"left\" bgcolor=\"#0080c0\" valign=\"top\"><b><font color=\"#ffffff\" face=\"Arial,Helvetica\">\n"); + gStream.print("Detailed performance data grouped by scenario prefix</font></b></td></tr></tbody></table>\n"); + gStream.print("<a href=\"org.eclipse.ant.php?\">org.eclipse.ant*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.compare.php?\">org.eclipse.compare*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.core.php?\">org.eclipse.core*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.jdt.core.php?\">org.eclipse.jdt.core*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.jdt.debug.php?\">org.eclipse.jdt.debug*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.jdt.text.php?\">org.eclipse.jdt.text*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.jdt.ui.php?\">org.eclipse.jdt.ui*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.jface.php?\">org.eclipse.jface*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.osgi.php?\">org.eclipse.osgi*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.pde.api.tools.php?\">org.eclipse.pde.api.tools*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.pde.ui.php?\">org.eclipse.pde.ui*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.swt.php?\">org.eclipse.swt*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.team.php?\">org.eclipse.team*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.ua.php?\">org.eclipse.ua*</a><br>\n"); + gStream.print("<a href=\"org.eclipse.ui.php?\">org.eclipse.ui*</a><br><p><br><br>\n"); + gStream.print("</body>\n"); + gStream.print(Utils.HTML_CLOSE); + gStream.close(); + } else { + stream.print(Utils.HTML_OPEN); + } + 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); + + // Print title + stream.print("<body>"); + printComponentTitle(/*performanceResults, */component, isGlobal, stream); + + // print the html representation of fingerprint for each config + Display display = Display.getDefault(); + if (this.genFingerPrints || this.genAll) { + final FingerPrint fingerprint = new FingerPrint(component, stream, this.outputDir); + display.syncExec( + new Runnable() { + public void run(){ + try { + fingerprint.print(GenerateResults.this.performanceResults); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + ); + } +// FingerPrint fingerprint = new FingerPrint(component, stream, this.outputDir); +// fingerprint.print(performanceResults); + + // print scenario status table + if (!isGlobal) { + // print the component scenario status table beneath the fingerprint + final ScenarioStatusTable sst = new ScenarioStatusTable(component, stream); + display.syncExec( + new Runnable() { + public void run(){ + try { + sst.print(GenerateResults.this.performanceResults); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + ); +// ScenarioStatusTable sst = new ScenarioStatusTable(component, stream); +// sst.print(performanceResults); + } + + stream.print(Utils.HTML_CLOSE); + stream.close(); +} + +private void printComponentTitle(/*PerformanceResults performanceResults, */String component, boolean isGlobal, PrintStream stream) { + String baselineName = this.performanceResults.getBaselineName(); + String currentName = this.performanceResults.getName(); + + // Print title line + stream.print("<h3>Performance of "); + if (!isGlobal) { + stream.print(component); + stream.print(": "); + } + stream.print(currentName); + stream.print(" relative to "); + int index = baselineName.indexOf('_'); + if (index > 0) { + stream.print(baselineName.substring(0, index)); + stream.print(" ("); + index = baselineName.lastIndexOf('_'); + stream.print(baselineName.substring(index+1, baselineName.length())); + stream.print(')'); + } else { + stream.print(baselineName); + } + stream.print("</h3>\n"); + + // Print reference to global results + if (!isGlobal) { + stream.print("<?php\n"); + stream.print(" $type=$_SERVER['QUERY_STRING'];\n"); + stream.print(" if ($type==\"\") {\n"); + stream.print(" $type=\"fp_type=0\";\n"); + stream.print(" }\n"); + stream.print(" $href=\"<a href=\\\"performance.php?\";\n"); + stream.print(" $href=$href . $type . \"\\\">Back to global results</a><br><br>\";\n"); + stream.print(" echo $href;\n"); + stream.print("?>\n"); + } +} + +/* + * Print summary of coefficient of variation for each scenario of the given pattern + * both for baseline and current builds. + */ +private void printSummary(/*PerformanceResults performanceResults*/) { + long start = System.currentTimeMillis(); + if (this.printStream != null) this.printStream.print("Print scenarios variations summary..."); + File outputFile = new File(this.outputDir, "cvsummary.html"); + PrintStream stream = null; + try { + stream = new PrintStream(new BufferedOutputStream(new FileOutputStream(outputFile))); + printSummaryPresentation(stream); +// List scenarioNames = DB_Results.getScenarios(); +// int size = scenarioNames.size(); + String[] components = this.performanceResults.getComponents(); + int componentsLength = components.length; + printSummaryColumnsTitle(stream/*, performanceResults*/); + String[] configs = this.performanceResults.getConfigNames(true/*sorted*/); + int configsLength = configs.length; + for (int i=0; i<componentsLength; i++) { + String componentName = components[i]; + List scenarioNames = this.performanceResults.getComponentScenarios(componentName); + int size = scenarioNames.size(); + for (int s=0; s<size; s++) { + String scenarioName = ((ScenarioResults) scenarioNames.get(s)).getName(); + if (scenarioName == null) continue; + ScenarioResults scenarioResults = this.performanceResults.getScenarioResults(scenarioName); + if (scenarioResults != null) { + stream.print("<tr>\n"); + for (int j=0; j<2; j++) { + for (int c=0; c<configsLength; c++) { + printSummaryScenarioLine(j, configs[c], scenarioResults, stream); + } + } + stream.print("<td>"); + stream.print(scenarioName); + stream.print("</td></tr>\n"); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + stream.print("</table></body></html>\n"); + stream.flush(); + stream.close(); + } + if (this.printStream != null) this.printStream.println("done in "+(System.currentTimeMillis()-start)+"ms"); +} + +/* + * Print summary presentation (eg. file start and text presenting the purpose of this file contents).. + */ +private void printSummaryPresentation(PrintStream stream) { + stream.print(Utils.HTML_OPEN); + stream.print(Utils.HTML_DEFAULT_CSS); + stream.print("<title>Summary of Elapsed Process Variation Coefficients</title></head>\n"); + stream.print("<body><h3>Summary of Elapsed Process Variation Coefficients</h3>\n"); + stream.print("<p> This table provides a bird's eye view of variability in elapsed process times\n"); + stream.print("for baseline and current build stream performance scenarios."); + stream.print(" This summary is provided to facilitate the identification of scenarios that should be examined due to high variability."); + stream.print("The variability for each scenario is expressed as a <a href=\"http://en.wikipedia.org/wiki/Coefficient_of_variation\">coefficient\n"); + stream.print("of variation</a> (CV). The CV is calculated by dividing the <b>standard deviation\n"); + stream.print("of the elapse process time over builds</b> by the <b>average elapsed process\n"); + stream.print("time over builds</b> and multiplying by 100.\n"); + stream.print("</p><p>High CV values may be indicative of any of the following:<br></p>\n"); + stream.print("<ol><li> an unstable performance test. </li>\n"); + stream.print("<ul><li>may be evidenced by an erratic elapsed process line graph.<br><br></li></ul>\n"); + stream.print("<li>performance regressions or improvements at some time in the course of builds.</li>\n"); + stream.print("<ul><li>may be evidenced by plateaus in elapsed process line graphs.<br><br></li></ul>\n"); + stream.print("<li>unstable testing hardware.\n"); + stream.print("<ul><li>consistent higher CV values for one test configuration as compared to others across"); + stream.print(" scenarios may be related to hardward problems.</li></ul></li></ol>\n"); + stream.print("<p> Scenarios are listed in alphabetical order in the far right column. A scenario's\n"); + stream.print("variation coefficients (CVs) are in columns to the left for baseline and current\n"); + stream.print("build streams for each test configuration. Scenarios with CVs > 10% are highlighted\n"); + stream.print("in yellow (10%<CV><CV<20%) and orange(CV>20%). </p>\n"); + stream.print("<p> Each CV value links to the scenario's detailed results to allow viewers to\n"); + stream.print("investigate the variability.</p>\n"); +} + +/* + * Print columns titles of the summary table. + */ +private void printSummaryColumnsTitle(PrintStream stream/*, PerformanceResults performanceResults*/) { + String[] configBoxes = this.performanceResults.getConfigBoxes(true/*sorted*/); + int length = configBoxes.length; + stream.print("<table border=\"1\"><tr><td colspan=\""); + stream.print(length); + stream.print("\"><b>Baseline CVs</b></td><td colspan=\""); + stream.print(length); + stream.print("\"><b>Current Build Stream CVs</b></td><td rowspan=\"2\"><b>Scenario Name</b></td></tr>\n"); + stream.print("<tr>"); + for (int n=0; n<2; n++) { + for (int c=0; c<length; c++) { + stream.print("<td>"); + stream.print(configBoxes[c]); + stream.print("</td>"); + } + } + stream.print("</tr>\n"); +} + +/* + * Print a scenario line in the summary table. + */ +private void printSummaryScenarioLine(int i, String config, ScenarioResults scenarioResults, PrintStream stream) { + ConfigResults configResults = scenarioResults.getConfigResults(config); + if (configResults == null || !configResults.isValid()) { + stream.print("<td>n/a</td>"); + return; + } + String url = config + "/" + scenarioResults.getFileName()+".html"; + double[] stats = null; + if (i==0) { // baseline results + List baselinePrefixes; + if (this.baselinePrefix == null) { + baselinePrefixes = Util.BASELINE_BUILD_PREFIXES; + } else { + baselinePrefixes = new ArrayList(); + baselinePrefixes.add(this.baselinePrefix); + } + stats = configResults.getStatistics(baselinePrefixes); + } else { + stats = configResults.getStatistics(this.currentBuildPrefixes); + } + double variation = stats[3]; + if (variation > 0.1 && variation < 0.2) { + stream.print("<td bgcolor=\"yellow\">"); + } else if (variation >= 0.2) { + stream.print("<td bgcolor=\"FF9900\">"); + } else { + stream.print("<td>"); + } + stream.print("<a href=\""); + stream.print(url); + stream.print("\"/>"); + stream.print(Util.PERCENTAGE_FORMAT.format(variation)); + stream.print("</a></td>"); +} + +/* + * Print usage in case one of the argument of the line was incorrect. + * Note that calling this method ends the program run due to final System.exit() + */ +private void printUsage() { + System.out.println( + "Usage:\n\n" + + "-baseline\n" + + " Build id against which to compare results.\n" + + " Same as value specified for the \"build\" key in the eclipse.perf.config system property.\n\n" + + + "[-baseline.prefix]\n" + + " Optional. Build id prefix used in baseline test builds and reruns. Used to plot baseline historical data.\n" + + " A common prefix used for the value of the \"build\" key in the eclipse.perf.config system property when rerunning baseline tests.\n\n" + + + "-current\n" + + " build id for which to generate results. Compared to build id specified in -baseline parameter above.\n" + + " Same as value specified for the \"build\" key in the eclipse.perf.config system property. \n\n" + + + "[-current.prefix]\n" + + " Optional. Comma separated list of build id prefixes used in current build stream.\n" + + " Used to plot current build stream historical data. Defaults to \"N,I\".\n" + + " Prefixes for values specified for the \"build\" key in the eclipse.perf.config system property. \n\n" + + + "-jvm\n" + + " Value specified in \"jvm\" key in eclipse.perf.config system property for current build.\n\n" + + + "-config\n" + + " Comma separated list of config names for which to generate results.\n" + + " Same as values specified in \"config\" key in eclipse.perf.config system property.\n\n" + + + "-output\n" + + " Path to default output directory.\n\n" + + + "[-config.properties]\n" + + " Optional. Used by scenario status table to provide the following:\n" + + " alternate descriptions of config values to use in columns.\n" + + " The value should be specified in the following format:\n" + + " name1,description1;name2,description2;etc..\n\n" + + + "[-highlight]\n" + + " Optional. Comma-separated list of build Id prefixes used to find most recent matching for each entry.\n" + + " Result used to highlight points in line graphs.\n\n" + + + "[-scenario.pattern]\n" + + " Optional. Scenario prefix pattern to query database. If not specified,\n" + + " default of % used in query.\n\n" + + + "[-fingerprints]\n" + + " Optional. Use to generate fingerprints only.\n\n" + + + "[-data]\n" + + " Optional. Generates table of scenario reference and current data with line graphs.\n\n" + + + "[-print]\n" + + " Optional. Display output in the console while generating.\n" + + + "[-nophp]\n" + + " Optional. Generate files for non-php server.\n" + + + "[-failure.threshold]\n" + + " Optional. Set the failure percentage threshold (default is 10%).\n" + ); + + System.exit(1); +} + +/** + * Run the generation from a list of arguments. + * Typically used to generate results from an application. + */ +public IStatus run(String[] args) { + parse(args); + return run((IProgressMonitor) null); +} + +/** + * Run the generation using a progress 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) { + long begin = System.currentTimeMillis(); + int work = 1100; + int dataWork = 1000 * this.performanceResults.getConfigBoxes(false).length; + if (this.genAll || this.genData) { + work += dataWork; + } + SubMonitor subMonitor = SubMonitor.convert(monitor, work); + try { + + // Print whole scenarios summary + if (this.printStream != null) this.printStream.println(); + printSummary(/*performanceResults*/); + + // Copy images and scripts to output dir + Bundle bundle = UiPlugin.getDefault().getBundle(); +// URL images = bundle.getEntry("images"); +// if (images != null) { +// images = FileLocator.resolve(images); +// Utils.copyImages(new File(images.getPath()), this.outputDir); +// } + /* New way to get images + File content = FileLocator.getBundleFile(bundle); + BundleFile bundleFile; + if (content.isDirectory()) { + bundleFile = new DirBundleFile(content); + Utils.copyImages(bundleFile.getFile("images", true), this.outputDir); + } else { + bundleFile = new ZipBundleFile(content, null); + Enumeration imageFiles = bundle.findEntries("images", "*.gif", false); + while (imageFiles.hasMoreElements()) { + URL url = (URL) imageFiles.nextElement(); + Utils.copyFile(bundleFile.getFile("images"+File.separator+, true), this.outputDir); + } + } + */ + // Copy bundle files + Utils.copyBundleFiles(bundle, "images", "*.gif", this.outputDir); // images + Utils.copyBundleFiles(bundle, "scripts", "*.js", this.outputDir); // java scripts + Utils.copyBundleFiles(bundle, "scripts", "*.css", this.outputDir); // styles + Utils.copyBundleFiles(bundle, "doc", "*.html", this.outputDir); // doc + Utils.copyBundleFiles(bundle, "doc/images", "*.png", this.outputDir); // images for doc + /* + URL doc = bundle.getEntry("doc"); + if (doc != null) { + doc = FileLocator.resolve(doc); + File docDir = new File(doc.getPath()); + FileFilter filter = new FileFilter() { + public boolean accept(File pathname) { + return !pathname.getName().equals("CVS"); + } + }; + File[] docFiles = docDir.listFiles(filter); + for (int i=0; i<docFiles.length; i++) { + File file = docFiles[i]; + if (file.isDirectory()) { + File subdir = new File(this.outputDir, file.getName()); + subdir.mkdir(); + File[] subdirFiles = file.listFiles(filter); + for (int j=0; j<subdirFiles.length; j++) { + if (subdirFiles[i].isDirectory()) { + // expect only one sub-directory + } else { + Util.copyFile(subdirFiles[j], new File(subdir, subdirFiles[j].getName())); + } + } + } else { + Util.copyFile(file, new File(this.outputDir, file.getName())); + } + } + } + */ + + // Print HTML pages and all linked files + if (this.printStream != null) { + this.printStream.println("Print performance results HTML pages:"); + this.printStream.print(" - components main page"); + } + long start = System.currentTimeMillis(); + subMonitor.setTaskName("Write fingerprints: 0%"); + subMonitor.subTask("Global..."); + printComponent(/*performanceResults, */"global_fp"); + subMonitor.worked(100); + if (subMonitor.isCanceled()) throw new OperationCanceledException(); + String[] components = this.performanceResults.getComponents(); + int length = components.length; + int step = 1000 / length; + 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]+"..."); + printComponent(/*performanceResults, */components[i]); + subMonitor.worked(step); + if (subMonitor.isCanceled()) throw new OperationCanceledException(); + progress++; + } + if (this.printStream != null) { + String duration = Util.timeString(System.currentTimeMillis()-start); + this.printStream.println(" done in "+duration); + } + + // Print the scenarios data + if (this.genData || this.genAll) { + start = System.currentTimeMillis(); + if (this.printStream != null) this.printStream.println(" - all scenarios data:"); + ScenarioData data = new ScenarioData(this.baselinePrefix, this.pointsOfInterest, this.currentBuildPrefixes, this.outputDir); + try { + data.print(this.performanceResults, this.printStream, subMonitor.newChild(dataWork)); + } catch (Exception ex) { + ex.printStackTrace(); + } + if (this.printStream != null) { + String duration = Util.timeString(System.currentTimeMillis()-start); + this.printStream.println(" => done in "+duration); + } + } + if (this.printStream != null) { + long time = System.currentTimeMillis(); + this.printStream.println("End of generation: "+new SimpleDateFormat("H:mm:ss").format(new Date(time))); + String duration = Util.timeString(System.currentTimeMillis()-begin); + this.printStream.println("=> done in "+duration); + } + return new Status(IStatus.OK, UiPlugin.getDefault().toString(), "Everything is OK"); + } + catch (OperationCanceledException oce) { + return new Status(IStatus.OK, UiPlugin.getDefault().toString(), "Generation was cancelled!"); + } + catch (Exception ex) { + return new Status(IStatus.ERROR, UiPlugin.getDefault().toString(), "An unexpected exception occurred!", ex); + } + finally { + if (this.printStream != null) { + this.printStream.flush(); + if (this.printStream != System.out) { + this.printStream.close(); + } + } + } +} + +private void setDefaults(String buildName, String baseline) { + if (buildName == null) { + buildName = this.performanceResults.getName(); + } + + // Set default output dir if not set + if (this.outputDir.getPath().indexOf(buildName) == -1) { + File dir = new File(this.outputDir, buildName); + if (dir.exists() || dir.mkdir()) { + this.outputDir = dir; + if (this.printStream != null) { + this.printStream.println(" + changed output dir to: "+dir.getPath()); + } + } + } + + // Verify that build is known + String[] builds = this.performanceResults.getAllBuildNames(); + if (builds == null || builds.length == 0) { + System.err.println("Cannot connect to database to generate results build '"+buildName+"'"); + System.exit(1); + } + if (Arrays.binarySearch(builds, buildName, Util.BUILD_DATE_COMPARATOR) < 0) { + throw new RuntimeException("No results in database for build '"+buildName+"'"); + } + if (this.printStream != null) { + this.printStream.println(); + this.printStream.flush(); + } + + // Init baseline prefix if not set + if (this.baselinePrefix == null) { + int index = baseline.lastIndexOf('_'); + if (index > 0) { + this.baselinePrefix = baseline.substring(0, index); + } else { + this.baselinePrefix = DB_Results.getDbBaselinePrefix(); + } + } + + // Init current build prefixes if not set + if (this.currentBuildPrefixes == null) { + this.currentBuildPrefixes = new ArrayList(); + if (buildName.charAt(0) == 'M') { + this.currentBuildPrefixes.add("M"); + } else { + this.currentBuildPrefixes.add("N"); + } + this.currentBuildPrefixes.add("I"); + } +} + +private void setPerformanceResults(String buildName, String baselineName) { + + // Set performance results + this.performanceResults = new PerformanceResults(buildName, baselineName, this.baselinePrefix, this.printStream); + + // Set defaults + setDefaults(buildName, this.performanceResults.getBaselineName()); + + // Read performance results data + this.performanceResults.readAll(buildName, this.configDescriptors, this.scenarioPattern, this.dataDir, this.failure_threshold, null); +} + +/* (non-Javadoc) + * @see org.eclipse.equinox.app.IApplication#stop() + */ +public void stop() { + // Do nothing +} + +}
\ No newline at end of file |