How to do Benchmark : Debug « Development Class « Java






How to do Benchmark

      

/*
 * Copyright (c) 1996, 1997 by Doug Bell <dbell@shvn.com>.  All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */


import java.awt.Button;
import java.awt.Checkbox;
import java.awt.Event;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Label;
import java.awt.List;
import java.awt.TextArea;

public class BenchmarkApplet extends java.applet.Applet
  implements BenchmarkRunner, Runnable
{
  static final String spaces =
              "                                                       ";
  static final String newline = System.getProperty("line.separator");

  private volatile boolean  running;
  private int         estimatatedSeconds;
  private ThreadGroup     tgroup;
  private Thread        testTask;
  private List        testList;
  private TextArea      out;
  private Label       timeEstimate;
  private Button        doit, abort, clear;
  private Checkbox      console;
  private Benchmark[]     tests = {
                  new Benchmark(this),
                  new MixedBenchmark(this),
                  new LoopBenchmark(this),
                  new VariableBenchmark(this),
                  new MethodBenchmark(this),
                  new OperatorBenchmark(this),
                  new CastingBenchmark(this),
                  new InstantiationBenchmark(this),
                  new ExceptionBenchmark(this)
                };


  public void init () {
    tgroup = Thread.currentThread().getThreadGroup();

    Font    font = new Font("Courier", Font.PLAIN, 10);
    FontMetrics fm = getFontMetrics(font);
    int     lines = Math.max(10, size().height / fm.getHeight() - 4);

    out = new TextArea(lines, spaces.length() + Benchmark.resolutionName.length());
    out.setFont(font);
    out.setEditable(false);
    add(out);

    boolean toobig;
    do {
      testList = new List(--lines, true);
      add(testList, 0);
      validate();
      if (toobig = testList.size().height - out.size().height > 2)
        remove(testList);
    } while (toobig);
    for (int ii = 0;  ii < tests.length;  ii++)
      testList.addItem(tests[ii].getName());
    testList.select(0);   // Calibration benchmark
    testList.select(1);   // Mixed benchmark

    timeEstimate = new Label(getTimeEstimate());
    add(timeEstimate);

    add(doit  = new Button("Run Benchmark"));
    add(abort = new Button("Stop"));
    add(clear = new Button("Clear"));
    abort.disable();
    clear.disable();

    add(console = new Checkbox("Console"));

    validate();
  }


  public void start () {
    Benchmark.recalibrate();
  }


  public synchronized void run () {
    try {
      running = true;
      timingTests();
    }
    finally {
      running = false;
      doit.enable();
      abort.disable();
    }
  }


  public boolean action (Event evt, Object arg) {
    if (evt.target == doit) {
      if (!running) {
        testTask = new Thread(tgroup, this);
        testTask.start();
      }
      return true;
    }
    else if (evt.target == abort) {
      if (running) {
        testTask.stop();
        println("*** aborted by user ***");
      }
      return true;
    }
    else if (evt.target == clear) {
      out.setText("");
      clear.disable();
      return true;
    }
    return false;
  }


  public boolean handleEvent (Event evt) {
    if (evt.target == testList) {
      if (evt.id == Event.LIST_SELECT  ||  evt.id == Event.LIST_DESELECT)
        if (timeEstimate != null)
          timeEstimate.setText(getTimeEstimate());
    }
    return super.handleEvent(evt);
  }


  private void timingTests () {
    int   cnt, testSeconds = 0;
    long  begin = System.currentTimeMillis();

    doit.disable();
    abort.enable();
    Benchmark.gc();
    println(newline +
        "Benchmark tests:  [mem=" + Runtime.getRuntime().freeMemory() +"/" +
                      Runtime.getRuntime().totalMemory() +"]");

    for (cnt = 0;  cnt < testList.countItems();  cnt++)
      if (testList.isSelected(cnt))
        testSeconds += tests[cnt].getTestTime();
    println("Estimated time: " + timeString(estimatatedSeconds) + " (tests " +
        timeString(testSeconds) + ")");

    long total = 0;
    for (cnt = 0;  cnt < testList.countItems();  cnt++)
      if (testList.isSelected(cnt))
        total += tests[cnt].runTest();

    println("*** done: " +
        timeString((int) (System.currentTimeMillis() + 500 - begin) / 1000) +
        " (tests " +
        timeString((int) ((total + 500) / 1000)) +
        ") ***");
  }


  static String timeString (int seconds) {
    int sec = seconds % 60;
    return (seconds / 60) + ((sec < 10) ? ":0" : ":") + sec;
  }

  private String getTimeEstimate () {
    estimatatedSeconds = 0;
    for (int cnt = 0;  cnt < testList.countItems();  cnt++)
      if (testList.isSelected(cnt))
        estimatatedSeconds += tests[cnt].getRunningTime();
    return "Estimated running time: " + timeString(estimatatedSeconds);
  }


  public void report (String msg, long nanos) {
    if (msg != null) {
      String  time = Long.toString(nanos);
      int   index = msg.length() + time.length();
      String  space = (index >= spaces.length()) ? " " : spaces.substring(index);
      println(msg + space + time + Benchmark.resolutionName);
    }
  }

  public synchronized void println (String s) {
    if (console.getState())
      System.out.println(s);
    out.appendText(s + newline);
    clear.enable();
    Thread.yield();  // give interface a chance to process events
  }
}  // class BenchmarkApplet

// EOF


/*
 * Copyright (c) 1996, 1997 by Doug Bell <dbell@shvn.com>.  All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */


class DerivedObject {}
class DerivedObject2 extends DerivedObject {}
class DerivedObject3 extends DerivedObject2 {}
class DerivedObject4 extends DerivedObject3 {}
class DerivedObject5 extends DerivedObject4 {}

interface Inter1 {}
interface Inter2 extends Inter1 {}
interface Inter3 extends Inter2 {}
interface Inter4 extends Inter3 {}
interface Inter5 extends Inter4 {}
interface Inter6 extends Inter5 {}


/*
 * This is the base benchmark class.  To create a new benchmark, extend this class and
 * implement getTestTime(), getRunningTime() and runTest() in the extended class.
 */

 class Benchmark implements Runnable {
  private static boolean    calibrated;
  private static long     gcMemTarget;
  private static String[]   resNames = {" ms", " s", " ns", " ps"};
  private static long[]   resValues = {1000L, 1000000L, 1000000000L, 1000000000000L};

  protected static int    resIndex = 2;   // ns = nanosecond
  protected static String   resolutionName = resNames[resIndex];
  protected static long   resolution = resValues[resIndex];
  protected static long   timerLoopNanos;
  protected static int[]    useint = new int[3]; // used to prevent dead variable elimination

  private BenchmarkRunner   runner;
  private Thread        timer;
  private long        sampleMillis = 1000L; // 1 second for each test
  private int         sampleCount = 3;
  private int         timerIterations;
  private boolean       timerPaused;
  private long        timerStart, reportMillis;
  private int[]       iterations = new int[sampleCount];
  private long[]        milliseconds = new long[sampleCount];

  protected long        timerMillis, totalMillis;
  protected volatile boolean  go;


  public static void gc () {
    System.runFinalization();
    System.gc();
    if (Runtime.getRuntime().freeMemory() < gcMemTarget) {
      try {
        int[] mem = new int[(int) gcMemTarget/4];
        mem = null;
      }
      catch (OutOfMemoryError e) {
        gcMemTarget -= 10000;
        recalibrate();
      }
      System.gc();
    }
    try { Thread.sleep(100); } catch (InterruptedException e) {}
  }


  public static void recalibrate () {
    calibrated = false;
  }


  public static void calibrate () {
    calibrated = false;
    new Benchmark().runTest();
    if (timerLoopNanos < 98) {
      if (resIndex < resValues.length - 1) {
        resIndex++;
        resolutionName = resNames[resIndex];
        resolution = resValues[resIndex];
        calibrate();
      }
    }
    else if (timerLoopNanos > 102000) {
      if (resIndex > 0) {
        resIndex--;
        resolutionName = resNames[resIndex];
        resolution = resValues[resIndex];
        calibrate();
      }
    }
    if (!calibrated) {
      gcMemTarget = 0;
      gc();
      long sysmem = Math.min(1000000, Runtime.getRuntime().totalMemory() - 10000);
      gcMemTarget = Math.min(1000000, Runtime.getRuntime().freeMemory() - 5000);
      if (true|| gcMemTarget < 200000  &&  sysmem > gcMemTarget) {
        boolean ok;
        gcMemTarget = sysmem;
        do {
          ok = true;
          try {
            int[] mem = new int[(int) gcMemTarget/4];
            mem = null;
          }
          catch (OutOfMemoryError e) {
            gcMemTarget -= 10000;
            ok = false;
          }
        } while (!ok);
      }
      gcMemTarget = Math.min(sysmem, gcMemTarget);
      calibrated = true;
    }
  }


  static long getNanos (long[] millis, int[] iterations, long overheadNanos) {
    long nanos = resolution * 100;
    for (int ii = Math.min(millis.length, iterations.length);  --ii >= 0; ) {
      if (iterations[ii] > 0)
        nanos = Math.min(nanos,
                 (((resolution/1000) * millis[ii]) / iterations[ii]) -
                  overheadNanos);
      iterations[ii] = 0;
      millis[ii] = 0;
    }
    return nanos;
  }


  Benchmark () {
    this(null);
  }

  Benchmark (BenchmarkRunner runner) {
    this.runner = runner;
  }


  /** Returns the name of the test.
   *  Default implementation uses the unqualified class name, stripping 'Benchmark'
   *  from the name if it exists.
   */
  public String getName () {
    String name = getClass().getName();
    int index = name.lastIndexOf('.');
    name = name.substring(index < 0 ? 0 : index);
    if (name.equals("Benchmark"))
      name = "Calibrate";
    else if (name.endsWith("Benchmark"))
      name = name.substring(0, name.length() - "Benchmark".length());
    return name;
  }


  /** Returns approximate running time of justs the timing tests, in seconds.
   *  Subclass should override this method.
   */
  public int getTestTime () {
    return (int) (getSampleCount() * getSampleMillis()) / 1000;
  }


  /** Returns approximate total running time of the benchmark, in seconds.
   *  Subclass should override this method.
   */
  public int getRunningTime () {
    return getTestTime();
  }


  /** Set the number of samples to measure for a test.
   */
  final void setSampleCount (int samples) {
    if (samples != sampleCount  &&  samples > 0) {
      sampleCount = samples;
      iterations = new int[samples];
      milliseconds = new long[samples];
    }
  }

  /** Get the number of samples to measure for a test.
   */
  final int getSampleCount () {
    return sampleCount;
  }


  /** Set the number of milliseconds to run the timer.
   */
  final void setSampleMillis (long millis) {
    if (millis > 0)
      sampleMillis = millis;
  }

  /** Get the number of milliseconds to run the timer.
   */
  final long getSampleMillis () {
    return sampleMillis;
  }


  /** Should be called at the beginning of runTest().
   */
  protected void startTest () {
    println("");
    println("

   
    
    
    
    
    
  








Related examples in the same category

1.A simple logging facility.
2.Debug Utilities
3.Debug InputStream
4.Methods for printing Debug messages
5.Trace InputStream
6.Trace OutputStream
7.Debug Utility
8.Debugging utility that reports, in a brute force manner, any internal data of a class instance
9.Swing Console
10.Methods for logging events
11.Printing indented text
12.Prints messages formatted for a specific line width.
13.Class providing static methods to log diagnostics
14.A bean that can be used to keep track of a counter
15.An integer synchronized counter class.
16.Counts down from a specified value the number of bytes actually read from the wrapped InputStream.
17.A long integer counter class
18.Logging class to record errors or unexpected behavior to a file
19.Handle obtaining string timestamps
20.Scans java source files in cvs tree and validates the license header
21.Debug Util
22.Array debug util
23.A simple frame that allows quick and easy visualisation of something