diff options
Diffstat (limited to 'basebuilder-3.6.2/org.eclipse.releng.basebuilder/plugins/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/BuildResults.java')
-rw-r--r-- | basebuilder-3.6.2/org.eclipse.releng.basebuilder/plugins/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/BuildResults.java | 588 |
1 files changed, 588 insertions, 0 deletions
diff --git a/basebuilder-3.6.2/org.eclipse.releng.basebuilder/plugins/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/BuildResults.java b/basebuilder-3.6.2/org.eclipse.releng.basebuilder/plugins/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/BuildResults.java new file mode 100644 index 0000000..21e3021 --- /dev/null +++ b/basebuilder-3.6.2/org.eclipse.releng.basebuilder/plugins/org.eclipse.test.performance.ui/src/org/eclipse/test/internal/performance/results/db/BuildResults.java @@ -0,0 +1,588 @@ +/******************************************************************************* + * 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.db; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.text.ParseException; +import java.util.StringTokenizer; + +import org.eclipse.test.internal.performance.InternalPerformanceMeter; +import org.eclipse.test.internal.performance.PerformanceTestPlugin; +import org.eclipse.test.internal.performance.data.Dim; +import org.eclipse.test.internal.performance.results.utils.Util; + +/** + * Class providing numbers of a scenario running on a specific configuration + * at a specific time (for example 'I20070615-1200'). + */ +public class BuildResults extends AbstractResults { + + private static final double IMPOSSIBLE_VALUE = -1E6; + + // Build information + String date; + String comment; + int summaryKind = -1; + + // Dimensions information + Dim[] dimensions; + double[] average, stddev; + long[] count; + double[][] values; + boolean hadValues = false; + private int defaultDimIndex = -1; + + // Comparison information + boolean baseline; + String failure; + +BuildResults(AbstractResults parent) { + super(parent, -1); +} + +BuildResults(AbstractResults parent, int id) { + super(parent, id); + this.name = DB_Results.getBuildName(id); + this.baseline = this.name.startsWith(DB_Results.getDbBaselinePrefix()); +} + +/* + * Clean values when several measures has been done for the same build. + */ +void cleanValues() { + int length = this.values.length; + for (int dim_id=0; dim_id<length; dim_id++) { + int vLength = this.values[dim_id].length; + /* Log clean operation + if (dim_id == 0) { + IStatus status = new Status(IStatus.WARNING, PerformanceTestPlugin.PLUGIN_ID, "Clean "+vLength+" values for "+this.parent+">"+this.name+" ("+this.count[dim_id]+" measures)..."); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$ //$NON-NLS-5$ + PerformanceTestPlugin.log(status); + } + */ + this.average[dim_id] = 0; + for (int i=0; i<vLength; i++) { + this.average[dim_id] += this.values[dim_id][i]; + } + this.average[dim_id] /= vLength; + double squaredDeviations= 0; + for (int i=0; i<vLength; i++) { + double deviation= this.average[dim_id] - this.values[dim_id][i]; + squaredDeviations += deviation * deviation; + } + this.stddev[dim_id] = Math.sqrt(squaredDeviations / (this.count[dim_id] - 1)); // unbiased sample stdev + this.values[dim_id] = null; + } + for (int i=0; i<length; i++) { + if (this.values[i] != null) { + return; + } + } + this.values = null; + this.hadValues = true; +} + +/** + * Compare build results using the date of the build. + * + * @see Comparable#compareTo(Object) + */ +public int compareTo(Object obj) { + if (obj instanceof BuildResults) { + BuildResults res = (BuildResults) obj; + return getDate().compareTo(res.getDate()); + } + return -1; +} + +/** + * Returns the most recent baseline build results. + * + * @return The {@link BuildResults baseline build results}. + * @see BuildResults + */ +public BuildResults getBaselineBuildResults() { + return ((ConfigResults)this.parent).getBaselineBuildResults(); +} + +/** + * Returns the comment associated with the scenario for the current build. + * + * @return The comment associated with the scenario for the current build + * or <code>null</code> if no comment was stored for it. + */ +public String getComment() { + return this.comment; +} + +/** + * Return the number of stored values for the default dimension + * + * @return the number of stored values for the default dimension + */ +public long getCount() { + if (this.defaultDimIndex < 0) { + this.defaultDimIndex = DB_Results.getDefaultDimensionIndex(); + } + return this.count[this.defaultDimIndex]; +} + +/** + * Return the number of stored values for the given dimension. + * + * @param dim_id The id of the dimension (see {@link Dim#getId()}) + * @return the number of stored values for the given dimension + * + */ +public long getCount(int dim_id) { + return this.count[getDimIndex(dim_id)]; +} + +/** + * Returns the date of the build which is a part of its name. + * + * @return The date of the build as yyyyMMddHHmm + */ +public String getDate() { + if (this.date == null) { + if (this.baseline) { + int length = this.name.length(); + this.date = this.name.substring(length-12, length); + } else { + char first = this.name.charAt(0); + if (first == 'N' || first == 'I' || first == 'M') { // TODO (frederic) should be buildIdPrefixes... + if (this.name.length() == 14) { + this.date = this.name.substring(1, 9)+this.name.substring(10, 14); + } else { + this.date = this.name.substring(1); + } + } else { + int length = this.name.length() - 12 /* length of date */; + for (int i=0; i<=length; i++) { + try { + String substring = i == 0 ? this.name : this.name.substring(i); + Util.DATE_FORMAT.parse(substring); + this.date = substring; // if no exception is raised then the substring has a correct date format => store it + break; + } catch(ParseException ex) { + // skip + } + } + } + } + } + return this.date; +} + +/** + * Returns the standard deviation of the default dimension computed + * while running the scenario for the current build. + * + * @return The value of the standard deviation + */ +public double getDeviation() { + if (this.defaultDimIndex < 0) { + this.defaultDimIndex = DB_Results.getDefaultDimensionIndex(); + } + return this.stddev[this.defaultDimIndex]; +} + +/** + * Returns the standard deviation of the given dimension computed + * while running the scenario for the current build. + * + * @param dim_id The id of the dimension (see {@link Dim#getId()}) + * @return The value of the standard deviation + */ +public double getDeviation(int dim_id) { + final int dimIndex = getDimIndex(dim_id); + return dimIndex < 0 ? 0 : this.stddev[dimIndex]; +} + +/** + * Returns the dimensions supported for the current build. + * + * @return An array of dimensions. + */ +public Dim[] getDimensions() { + return this.dimensions; +} + +/** + * Returns the kind of summary for the scenario of the current build. + * + * @return -1 if the scenario has no summary, 1 if it's a global summary, 0 otherwise. + */ +public int getSummaryKind() { + return this.summaryKind; +} + +/** + * Returns whether the current build had several values stored in database. + * + * @return <code>true</code> if the measure was committed several times, + * <code>false</code> otherwise. + */ +public boolean hadValues() { + return this.hadValues; +} + +/* + * Return the index of the dimension corresponding to the given + * dimension id (see {@link Dim#getId()}) + */ +int getDimIndex(int dim_id) { + if (this.dimensions == null) return -1; + int length = this.dimensions.length; + for (int i=0; i<length; i++) { + if (this.dimensions[i] == null) break; + if (this.dimensions[i].getId() == dim_id) { + return i; + } + } + return -1; +} + +/** + * Return the error computed while storing values for the default dimension + * + * @return the error of the measures stored for the default dimension + */ +public double getError() { + long n = getCount(); + if (n == 1) return Double.NaN; + return getDeviation() / Math.sqrt(n); +} + +/** + * Return the error computed while storing values for the given dimension. + * + * @param dim_id The id of the dimension (see {@link Dim#getId()}) + * @return the error of the measures stored for the given dimension + */ +public double getError(int dim_id) { + long n = getCount(dim_id); + if (n == 1) return Double.NaN; + return getDeviation(dim_id) / Math.sqrt(n); +} + +/** + * Return the failure message which may happened on this scenario + * while running the current build + * + * @return The failure message or <code>null</null> if the scenario passed. + */ +public String getFailure() { + return this.failure; +} + +/** + * Return the value of the performance result stored + * for the given dimension of the current build. + * + * @param dim_id The id of the dimension (see {@link Dim#getId()}) + * @return The value of the performance result + */ +public double getValue(int dim_id) { + int idx = getDimIndex(dim_id); + if (idx < 0) return Double.NaN; + return this.average[idx]; +} + +/** + * Return the value of the performance result stored + * for the default dimension of the current build. + * + * @return The value of the performance result + */ +public double getValue() { + if (this.defaultDimIndex < 0) { + this.defaultDimIndex = DB_Results.getDefaultDimensionIndex(); + } + return this.average[this.defaultDimIndex]; +} + +/** + * Returns whether the build is a baseline build or not. + * + * @return <code>true</code> if the build name starts with the baseline prefix + * (see {@link PerformanceResults#getBaselinePrefix()} or <code>false</code> + * otherwise. + */ +public boolean isBaseline() { + return this.baseline; +} + +/** + * Returns whether the build has a summary or not. Note that the summary + * may be global or not. + * + * @return <code>true</code> if the summary kind is equals to 0 or 1 + * <code>false</code> otherwise. + */ +public boolean hasSummary() { + return this.summaryKind >= 0; +} +/** + * Returns whether the build has a global summary or not. + * + * @return <code>true</code> if the summary kind is equals to 1 + * <code>false</code> otherwise. + */ +public boolean hasGlobalSummary() { + return this.summaryKind == 1; +} + +/* + * Returns a given pattern match the build name or not. + */ +boolean match(String pattern) { + if (pattern.equals("*")) return true; //$NON-NLS-1$ + if (pattern.indexOf('*') < 0 && pattern.indexOf('?') < 0) { + pattern += "*"; //$NON-NLS-1$ + } + StringTokenizer tokenizer = new StringTokenizer(pattern, "*?", true); //$NON-NLS-1$ + int start = 0; + String previous = ""; //$NON-NLS-1$ + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + if (!token.equals("*") && !token.equals("?")) { //$NON-NLS-1$ //$NON-NLS-2$ + if (previous.equals("*")) { //$NON-NLS-1$ + int idx = this.name.substring(start).indexOf(token); + if (idx < 0) return false; + start += idx; + } else { + if (previous.equals("?")) start++; //$NON-NLS-1$ + if (!this.name.substring(start).startsWith(token)) return false; + } + start += token.length(); + } + previous = token; + } + if (previous.equals("*")) { //$NON-NLS-1$ + return true; + } else if (previous.equals("?")) { //$NON-NLS-1$ + return this.name.length() == start; + } + return this.name.endsWith(previous); +} + +/* + * Read the build results data from the given stream. + */ +void readData(DataInputStream stream) throws IOException { + long timeBuild = stream.readLong(); + this.date = new Long(timeBuild).toString(); + byte kind = stream.readByte(); + this.baseline = kind == 0; + if (this.baseline) { + this.name = getPerformance().baselinePrefix + '_' + this.date; + } else { + String suffix = this.date.substring(0, 8) + '-' + this.date.substring(8); + switch (kind) { + case 1: + this.name = "N" + suffix; //$NON-NLS-1$ + break; + case 2: + this.name = "I" + suffix; //$NON-NLS-1$ + break; + case 3: + this.name = "M" + suffix; //$NON-NLS-1$ + break; + default: + this.name = stream.readUTF(); + break; + } + } + int length = stream.readInt(); + this.dimensions = new Dim[length]; + this.average = new double[length]; + this.stddev = new double[length]; + this.count = new long[length]; + for (int i=0; i<length; i++) { + int dimId = stream.readInt(); + DB_Results.storeDimension(dimId); + this.dimensions[i] = (Dim) PerformanceTestPlugin.getDimension(dimId); + this.average[i] = stream.readLong(); + this.count[i] = stream.readLong(); + this.stddev[i] = stream.readDouble(); + } + this.id = DB_Results.getBuildId(this.name); + + // read summary + this.summaryKind = stream.readInt(); + + // read comment + String str = stream.readUTF(); + if (str.length() > 0) { + this.comment = str; + } +} + +/* + * Set the build summary and its associated comment. + */ +void setComment(String comment) { + if (comment != null && this.comment == null) { + this.comment = comment; + } +} + +/* + * Set the build summary and its associated comment. + */ +void setSummary(int kind, String comment) { + this.comment = comment; + this.summaryKind = kind; +} + +/* + * Set the build failure. + */ +void setFailure(String failure) { + this.failure = failure; +} + +/* + * Set the build value from database information. + */ +void setValue(int dim_id, int step, long value) { + int length = DB_Results.getDimensions().length; + Dim dimension = (Dim) PerformanceTestPlugin.getDimension(dim_id); + int idx = 0; + if (this.dimensions == null){ + this.dimensions = new Dim[length]; + this.average = new double[length]; + this.stddev = new double[length]; + this.count = new long[length]; + this.dimensions[0] = dimension; + for (int i=0; i<length; i++) { + // init average numbers with an impossible value + // to clearly identify whether it's already set or not + // when several measures are made for the same build + this.average[i] = IMPOSSIBLE_VALUE; + } + } else { + length = this.dimensions.length; + for (int i=0; i<length; i++) { + if (this.dimensions[i] == null) { + this.dimensions[i] = dimension; + idx = i; + break; + } + if (this.dimensions[i].getId() == dim_id) { + idx = i; + break; + } + } + } + switch (step) { + case InternalPerformanceMeter.AVERAGE: + if (this.average[idx] != IMPOSSIBLE_VALUE) { + if (this.values == null) { + this.values = new double[length][]; + this.values[idx] = new double[2]; + this.values[idx][0] = this.average[idx]; + this.values[idx][1] = value; + this.average[idx] = IMPOSSIBLE_VALUE; + } else if (this.values[idx] == null) { + this.values[idx] = new double[2]; + this.values[idx][0] = this.average[idx]; + this.values[idx][1] = value; + this.average[idx] = IMPOSSIBLE_VALUE; + } + } else if (this.values != null && this.values[idx] != null) { + int vLength = this.values[idx].length; + System.arraycopy(this.values[idx], 0, this.values[idx] = new double[vLength+1], 0, vLength); + this.values[idx][vLength] = value; + } else { + this.average[idx] = value; + } + break; + case InternalPerformanceMeter.STDEV: + this.stddev[idx] += Double.longBitsToDouble(value); + break; + case InternalPerformanceMeter.SIZE: + this.count[idx] += value; + break; + } +} + +/* (non-Javadoc) + * @see org.eclipse.test.internal.performance.results.AbstractResults#toString() + */ +public String toString() { + StringBuffer buffer = new StringBuffer(this.name); + buffer.append(": "); //$NON-NLS-1$ + int length = this.dimensions.length; + for (int i=0; i<length; i++) { + if (i>0) buffer.append(", "); //$NON-NLS-1$ + buffer.append('['); + buffer.append(this.dimensions[i].getId()); + buffer.append("]="); //$NON-NLS-1$ + buffer.append(this.average[i]); + buffer.append('/'); + buffer.append(this.count[i]); + buffer.append('/'); + buffer.append(Math.round(this.stddev[i]*1000)/1000.0); + } + return buffer.toString(); +} + +/* + * Write the build results data in the given stream. + */ +void write(DataOutputStream stream) throws IOException { + long timeBuild = -1; + try { + timeBuild = Long.parseLong(getDate()); + } catch (NumberFormatException nfe) { + // do nothing + nfe.printStackTrace(); + } + stream.writeLong(timeBuild); + byte kind = 0; // baseline + if (!this.baseline) { + switch (this.name.charAt(0)) { + case 'N': + kind = 1; + break; + case 'I': + kind = 2; + break; + case 'M': + kind = 3; + break; + default: + kind = 4; + break; + } + } + stream.writeByte(kind); + if (kind == 4) { + stream.writeUTF(this.name); + } + int length = this.dimensions == null ? 0 : this.dimensions.length; + stream.writeInt(length); + for (int i=0; i<length; i++) { + stream.writeInt(this.dimensions[i].getId()); + stream.writeLong((long)this.average[i]) ; + stream.writeLong(this.count[i]); + stream.writeDouble(this.stddev[i]); + } + + // Write extra infos (summary, failure and comment) + stream.writeInt(this.summaryKind); + stream.writeUTF(this.comment == null ? "" : this.comment) ; //$NON-NLS-1$ +} + +} |