From: Martin Zaun Date: January 8 2011 5:46am Subject: bzr push into mysql-5.1-telco-7.1 branch (martin.zaun:4042 to 4043) List-Archive: http://lists.mysql.com/commits/128213 Message-Id: <201101080547.p07LhjZf017567@rcsinet13.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0551424447==" --===============0551424447== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline 4043 Martin Zaun 2011-01-07 [merge] merge from ndb-7.1-dbg64 to ndb-7.1 added: storage/ndb/test/crund/process.sh storage/ndb/test/crund/src/com/mysql/cluster/crund/ResultProcessor.java modified: storage/ndb/test/crund/build.xml 4042 jonas oreland 2011-01-06 [merge] ndb - mege 70 to 71 modified: storage/ndb/include/util/Bitmask.hpp storage/ndb/src/common/util/Bitmask.cpp storage/ndb/src/common/util/Makefile.am storage/ndb/src/ndbapi/trp_buffer.hpp === modified file 'storage/ndb/test/crund/build.xml' --- a/storage/ndb/test/crund/build.xml 2010-10-08 11:17:35 +0000 +++ b/storage/ndb/test/crund/build.xml 2011-01-08 05:43:07 +0000 @@ -293,6 +293,8 @@ + === 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."); + } +} --===============0551424447== 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/ # testament_sha1: 82cefc6d384de2fd651eb982bfaff9c08f7dd9a8 # timestamp: 2011-01-07 21:46:38 -0800 # source_branch: file:///Users/mz/mysql/ndb-7.1-opt1/ # base_revision_id: jonas@stripped # # Begin bundle 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 LWAshYKolKMmj2dj/xdyRThQkKOzllo= --===============0551424447==--