From: Martin Zaun Date: January 8 2011 5:44am Subject: bzr commit into mysql-5.1-telco-7.1 branch (martin.zaun:4043) List-Archive: http://lists.mysql.com/commits/128212 Message-Id: <201101080546.p0829TFj014143@rcsinet13.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============2033202701==" --===============2033202701== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///Users/mz/mysql/ndb-7.1-dbg64/ based on revid:martin.zaun@stripped 4043 Martin Zaun 2011-01-07 crund - added result processor class added: storage/ndb/test/crund/process.sh storage/ndb/test/crund/src/com/mysql/cluster/crund/ResultProcessor.java === added file 'storage/ndb/test/crund/process.sh' --- a/storage/ndb/test/crund/process.sh 1970-01-01 00:00:00 +0000 +++ b/storage/ndb/test/crund/process.sh 2011-01-08 05:44:51 +0000 @@ -0,0 +1,4 @@ +#!/bin/bash +echo "running result processor..." +java -classpath build com.mysql.cluster.crund.ResultProcessor $* +echo "done." === added file 'storage/ndb/test/crund/src/com/mysql/cluster/crund/ResultProcessor.java' --- a/storage/ndb/test/crund/src/com/mysql/cluster/crund/ResultProcessor.java 1970-01-01 00:00:00 +0000 +++ b/storage/ndb/test/crund/src/com/mysql/cluster/crund/ResultProcessor.java 2011-01-08 05:44:51 +0000 @@ -0,0 +1,418 @@ +/* -*- mode: java; c-basic-offset: 4; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=4:tabstop=4:smarttab: + * + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights + * reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +package com.mysql.cluster.crund; + +import java.util.Properties; +import java.util.List; +import java.util.ArrayList; +import java.text.ParseException; +import java.text.DecimalFormat; + +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.InputStream; + + +/** + * This class parses and processes the result files of the Crund benchmark. + */ +public class ResultProcessor { + + /** + * This class reports the results of the Crund benchmark. + */ + public interface ResultReporter { + + /** + * Reports a data series. + * + * @param tag a name for this data series + * @param op the names of the operations + * @param avg the average values + * @param avg the standard deviations + * @param avg the relative standard deviations + */ + void report(String tag, + String[] op, + double[] avg, + double[] sdev, + double[] rsdev); + } + + /** + * This class reports the results of the Crund benchmark. + */ + static public class SimpleResultReporter implements ResultReporter { + static protected final DecimalFormat df = new DecimalFormat("#.##"); + + /** + * + */ + public void report(String tag, + String[] op, + double[] avg, + double[] sdev, + double[] rsdev) { + out.println(); + out.println("tag = " + tag); + out.println(); + + // ops with large deviations + final double thres = 10.0; + final List problematic = new ArrayList(); + + for (int i = 0; i < op.length; i++) { + out.println("op = " + op[i]); + out.println("avg = " + df.format(avg[i])); + out.println("sdev = " + df.format(sdev[i])); + out.println("rsdev = " + df.format(rsdev[i]) + "%"); + out.println(); + + if (rsdev[i] > thres) { + problematic.add(df.format(rsdev[i]) + "%\t" + op[i]); + } + } + + if (problematic.size() > 1) { + out.println("operations with large deviations:"); + for (String p : problematic) { + out.println(" " + p); + } + } + } + } + + // console + static protected final PrintWriter out = new PrintWriter(System.out, true); + static protected final PrintWriter err = new PrintWriter(System.err, true); + + // shortcuts + static protected final String endl = System.getProperty("line.separator"); + + // result processor command-line arguments + static private final List propFileNames = new ArrayList(); + static private final List ilogFileNames = new ArrayList(); + + // result processor settings + protected final Properties props = new Properties(); + protected int warmupRuns; + protected int hotRuns; + + // result processor resources + protected ResultReporter reporter; + protected String[] header; + protected String ltag; + protected int nval; + protected double[] ravg; + protected double[] rdev; + + // ---------------------------------------------------------------------- + // result processor usage + // ---------------------------------------------------------------------- + + /** + * Prints a command-line usage message and exits. + */ + static protected void exitUsage() { + out.println("usage: [options] ..."); + out.println(" [-p ]... a properties file name"); + out.println(" [-h|--help] print usage message and exit"); + out.println(); + System.exit(1); // return an error code + } + + /** + * Parses the result processor's command-line arguments. + */ + static public void parseArguments(String[] args) { + for (int i = 0; i < args.length; i++) { + final String arg = args[i]; + if (arg.equals("-p")) { + if (i >= args.length) { + exitUsage(); + } + propFileNames.add(args[++i]); + } else if (arg.equals("-h") || arg.equals("--help")) { + exitUsage(); + } else if (arg.startsWith("-")) { + out.println("unknown option: " + arg); + exitUsage(); + } else { + ilogFileNames.add(args[i]); + } + } + + if (propFileNames.size() == 0) { + // XXX propFileNames.add("crundResult.properties"); + } + + if (ilogFileNames.size() == 0) { + out.println("missing input files"); + exitUsage(); + } + } + + // ---------------------------------------------------------------------- + + /** + * Creates an instance. + */ + public ResultProcessor() {} + + /** + * Runs the result processor. + */ + public void run() { + try { + init(); + + for (String fn : ilogFileNames) { + out.println(); + out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + out.println("reading log file: " + fn); + out.println("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + + BufferedReader ilog = null; + try { + ilog = new BufferedReader(new FileReader(fn)); + process(ilog); + } finally { + if (ilog != null) + ilog.close(); + } + } + + close(); + } catch (Exception ex) { + // end the program regardless of threads + out.println("caught " + ex); + ex.printStackTrace(); + System.exit(2); // return an error code + } + } + + // processes the log file + protected void process(BufferedReader ilog) + throws IOException, ParseException { + + int lineNo = 1; + String line; + while (true) { + line = ilog.readLine(); + if (line == null) { + return; // eof + } + lineNo++; + //out.println(line); + + // skip comments + if (line.startsWith("#")) { + continue; + } + + // parse empty line + if (line.equals("")) { + if (header != null) { + report(); + } + + header = null; + ltag = null; + ravg = null; + rdev = null; + continue; + } + + // parse header line + if (header == null) { + header = line.split("\\t"); + assert (header.length > 0); + + nval = 0; + ravg = new double[header.length]; + rdev = new double[header.length]; + continue; + } + + // parse value line + final String[] values = line.split("\\t"); + if (values.length != header.length) { + String msg = ("line # " + lineNo + + ": wrong number of tokens; " + + "expected: " + header.length + + ", found: " + values.length); + throw new ParseException(msg, 0); + } + nval++; + + // parse line tag + if (ltag == null) { + ltag = values[0]; + } else if (!ltag.equals(values[0])) { + String msg = ("line # " + lineNo + + ": unexpected line tag; " + + "expected: '" + ltag + "'" + + ", found: '" + values[0] + "'"); + throw new ParseException(msg, 0); + } + + // parse numbers + for (int i = 1; i < values.length; i++) { + long l; + try { + l = Long.valueOf(values[i]); + } catch (NumberFormatException e) { + String msg = ("line # " + lineNo + + ": " + e); + throw new ParseException(msg, i); + } + + // compute running averages and squared deviations + final double v = l; + final double oavg = ravg[i]; + final double navg = oavg + (v - oavg) / nval; + final double odev = rdev[i]; + final double ndev = odev + (v - oavg) * (v - navg); + ravg[i] = navg; + rdev[i] = ndev; + } + } + } + + protected void report() { + // result data + final int nops = header.length - 1; + final String[] op = new String[nops]; + final double[] avg = new double[nops]; + final double[] sdev = new double[nops]; + final double[] rsdev = new double[nops]; + + // compute results + for (int i = 1; i <= nops; i++) { + op[i-1] = header[i]; + avg[i-1] = ravg[i]; + sdev[i-1] = Math.sqrt(rdev[i] / nval); + rsdev[i-1] = (sdev[i-1] * 100.0) / avg[i-1]; + } + final String tag = header[0] + ", " + ltag; + + reporter.report(tag, op, avg, sdev, rsdev); + } + + // ---------------------------------------------------------------------- + // result processor intializers/finalizers + // ---------------------------------------------------------------------- + + // initializes the result processor's resources. + protected void init() throws Exception { + loadProperties(); + initProperties(); + printProperties(); + reporter = new SimpleResultReporter(); + } + + // releases the result processor's resources. + protected void close() throws Exception { + reporter = null; + props.clear(); + } + + // loads the result processor's properties from properties files + private void loadProperties() throws IOException { + out.println(); + for (String fn : propFileNames) { + out.println("reading properties file: " + fn); + InputStream is = null; + try { + is = new FileInputStream(fn); + props.load(is); + } finally { + if (is != null) + is.close(); + } + } + } + + // retrieves a property's value and parses it as a boolean + protected boolean parseBoolean(String k, boolean vdefault) { + final String v = props.getProperty(k); + return (v == null ? vdefault : Boolean.parseBoolean(v)); + } + + // retrieves a property's value and parses it as a signed decimal integer + protected int parseInt(String k, int vdefault) { + final String v = props.getProperty(k); + try { + return (v == null ? vdefault : Integer.parseInt(v)); + } catch (NumberFormatException e) { + final NumberFormatException nfe = new NumberFormatException( + "invalid value of property ('" + k + "', '" + + v + "')."); + nfe.initCause(e); + throw nfe; + } + } + + // initializes the result processor properties + protected void initProperties() { + //props.list(out); + out.print("setting properties ..."); + out.flush(); + + final StringBuilder msg = new StringBuilder(); + final String eol = System.getProperty("line.separator"); + + warmupRuns = parseInt("warmupRuns", 0); + if (warmupRuns < 0) { + msg.append("[ignored] warmupRuns: " + warmupRuns + eol); + warmupRuns = 0; + } + + if (msg.length() == 0) { + out.println(" [ok]"); + } else { + out.println(); + out.print(msg.toString()); + } + } + + // prints the result processor's properties + protected void printProperties() { + out.println(); + out.println("result processor settings ..."); + out.println("warmupRuns: " + warmupRuns); + } + + // ---------------------------------------------------------------------- + + static public void main(String[] args) { + System.out.println("ResultProcessor.main()"); + parseArguments(args); + new ResultProcessor().run(); + System.out.println(); + System.out.println("ResultProcessor.main(): done."); + } +} --===============2033202701== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/martin.zaun@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: martin.zaun@stripped # target_branch: file:///Users/mz/mysql/ndb-7.1-dbg64/ # testament_sha1: ed3d87955f6c0e81e5d155cce812d5ceb789c146 # timestamp: 2011-01-07 21:44:57 -0800 # base_revision_id: martin.zaun@stripped\ # hmq4hepuwzlyz8u1 # # Begin bundle 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 --===============2033202701==--