blob: 7bc2ae206d9c201e1ea527cc28d1959eb1c44a54 [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlbeans.test.performance.utils;
import org.apache.xmlbeans.XmlError;
import org.apache.xmlbeans.XmlOptions;
import org.openuri.perf.Custom;
import org.openuri.perf.Result;
import org.openuri.perf.ResultSetDocument;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
public class RunComparator
{
// This class compares the xml results file of 2 perf runs and checks differences in the numbers for each test case
// An optional 'tolerance' % deviation value can be provided which will result in only the cases that are beyond this
// value (+/-) getting reported
private ResultSetDocument resultsDocOne; // XmlObject for the first result set
private ResultSetDocument resultsDocTwo; // and the second
private double tolerance; // % deviation in test run numbers
// The computation of deviation for a given test scase is done as follows:
// (run1 - run2)/run1 as a %. Negative value implies regression, +ve implies improvement
public RunComparator(String runResultsXmlFilePath1, String runResultsXmlFilePath2, double tolerance) throws Exception
{
System.out.println("XMLBeans RunComparator - comparing Perf Runs...");
if ((runResultsXmlFilePath1 != null) && (runResultsXmlFilePath2 != null))
{
try
{
File resultsFileOne = new File(runResultsXmlFilePath1);
File resultsFileTwo = new File(runResultsXmlFilePath2);
if (tolerance > 100 || tolerance < 0)
{
throw(new Exception("Invalid input value for 'tolerance'"));
}
this.tolerance = tolerance;
// generate XmlObjects and validate against schema
XmlOptions validateOptions = new XmlOptions();
List errors = new ArrayList();
validateOptions.setErrorListener(errors);
resultsDocOne = ResultSetDocument.Factory.parse(resultsFileOne);
if (!resultsDocOne.validate(validateOptions))
{
System.out.println("Result Set XML Document " + runResultsXmlFilePath1 + "is not Valid against schema!");
for (Iterator iterator = errors.iterator(); iterator.hasNext();)
{
XmlError eachErr = (XmlError) iterator.next();
//System.out.println("Validation Error:" + eachErr.getMessage() + eachErr.getLine());
}
//throw new Exception("Invalid Results File " + runResultsXmlFilePath1);
}
errors.clear();
resultsDocTwo = ResultSetDocument.Factory.parse(resultsFileTwo);
if (!resultsDocTwo.validate(validateOptions))
{
System.out.println("Result Set XML Document " + runResultsXmlFilePath2 + "is not Valid against schema!");
for (Iterator iterator = errors.iterator(); iterator.hasNext();)
{
XmlError eachErr = (XmlError) iterator.next();
//System.out.println("Validation Error:" + eachErr.getMessage() + eachErr.getLine());
}
//throw new Exception("Invalid Results File " + runResultsXmlFilePath2);
}
}
catch (FileNotFoundException fne)
{
throw new Exception("Invalid results file(s) specified!");
}
catch (Exception e)
{
e.printStackTrace();
}
}
else
{
throw new Exception("Input File Path(s) in null!");
}
} // end constructor
private void compare()
{
// create a hashmap with first run results
Result[] res1 = resultsDocOne.getResultSet().getResultArray();
HashMap runOneHashMap = new HashMap();
for (int i = 0; i < res1.length; i++)
{
Result eachResult = res1[i];
//System.out.println("Name:" + eachResult.getName() + "\tnote:" + eachResult.getNote() + "\tTime:" + eachResult.getTime());
Custom[] custArr = eachResult.getCustomArray();
if ((custArr != null) || (custArr.length > 0))
{
for (int j=0; j < custArr.length; j++)
{
Custom eachCustomElem = custArr[j];
//System.out.println("Cust:" + eachCustomElem.getName() + "\tvalue:" + eachCustomElem.getValue());
String hashKey = eachResult.getName() + "_" + eachCustomElem.getName() + "_" + eachCustomElem.getValue();
//System.out.println("Key:" + hashKey);
//System.out.println("Val:" + eachResult.getTime());
// insert each result into the hashmap
runOneHashMap.put(hashKey, eachResult);
}
}
else
{
// every result should have a custom element but this is not always true, the generated results are invalid sometimes
System.out.println("Result Set 1, Custom Element Missing!:" + eachResult.getName());
}
}
// now iterate thro second result set and compare
Result[] res2 = resultsDocTwo.getResultSet().getResultArray();
for (int i = 0; i < res2.length; i++)
{
Result eachResult2 = res2[i];
Custom[] custArr2 = eachResult2.getCustomArray();
if ((custArr2 != null) || (custArr2.length > 0))
{
for (int j = 0; j < custArr2.length; j++)
{
Custom custom = custArr2[j];
String hashKeyToLookFor = eachResult2.getName() + "_" + custom.getName() + "_" + custom.getValue();
Result resFromHash = (Result) runOneHashMap.get(hashKeyToLookFor);
if(resFromHash != null)
{
if (resFromHash.getTime() == eachResult2.getTime())
{
// no-op
//System.out.println("MATCH:" + hashKeyToLookFor );
//System.out.println("First Result Set:" + runOneTime.longValue());
//System.out.println("Second Result Set:" + result2.getTime());
//System.out.println("------");
}
else
{
// compute diff here and compare with tolerence
double diffPercent = ((double) resFromHash.getTime() - (double) eachResult2.getTime()) / (double) resFromHash.getTime();
diffPercent *= 100;
//**System.out.println("% Change= " + diff);
String testDetails = "Test Case Name\t:" + resFromHash.getName() + "\n" +
"Test Case Spec\t:" + resFromHash.getCustomArray(j).getName() + "=" +
resFromHash.getCustomArray(j).getValue() + "\n" +
"Tolerance Spec\t:" + tolerance;
// regression
if (diffPercent < 0)
{
diffPercent *= -1.00;
if (diffPercent >= 0)
{
if (diffPercent > tolerance)
{
diffPercent *= -1.00;
System.out.println("Regression Found! \n" + testDetails + "\n" + "% Deviation\t\t:" + diffPercent);
System.out.println("------");
}
}
}
// improvement
if (diffPercent >= 0)
{
if (diffPercent > tolerance)
{
//System.out.println("Improvement Found! \n" + testDetails + "\n" + "% Deviation\t\t:" + diffPercent);
//System.out.println("------");
}
}
}
} // end of hashtable look up result null check
} // end for
}
else
{
// every result should have a custom element
System.out.println("Result Set 2, Custom Element Missing!::" + eachResult2.getName());
}
}
}
public static void main(String[] args) throws Exception
{
if((args.length > 3) || args.length < 2)
{
System.out.println("Invalid Number of arguments to RunComparator utility!");
System.out.println("Usage: java RunComparator <path to run output file 1> <path to run output file 2> [<tolerance>]");
System.exit(0);
}
// TODO: More checking here and add a driver ant task for this utility
String runOne = args[0];
String runTwo = args[1];
double tolerance = 5.00; // default value
if(args[2] != null)
{
tolerance = Double.parseDouble(args[2]);
}
RunComparator rc = new RunComparator(runOne, runTwo, tolerance);
rc.compare();
}
}