View Javadoc

    1   /**
    2    * Copyright (c) 2004-2011 QOS.ch
    3    * All rights reserved.
    4    *
    5    * Permission is hereby granted, free  of charge, to any person obtaining
    6    * a  copy  of this  software  and  associated  documentation files  (the
    7    * "Software"), to  deal in  the Software without  restriction, including
    8    * without limitation  the rights to  use, copy, modify,  merge, publish,
    9    * distribute,  sublicense, and/or sell  copies of  the Software,  and to
    10   * permit persons to whom the Software  is furnished to do so, subject to
    11   * the following conditions:
    12   *
    13   * The  above  copyright  notice  and  this permission  notice  shall  be
    14   * included in all copies or substantial portions of the Software.
    15   *
    16   * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
    17   * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
    18   * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
    19   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    20   * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    21   * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
    22   * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    23   *
    24   */
    25  package org.slf4j.helpers;
    26
    27  import junit.framework.AssertionFailedError;
    28
    29  /**
    30   * BogoPerf is used to check that the time required to perform a certain
    31   * operation does not deteriorate over time. BogoPerf adjusts to the CPU speed
    32   * and capabilities of the host.
    33   *
    34   * @author Ceki G&uuml;lc&uuml;
    35   *
    36   */
    37  public class BogoPerf {
    38
    39      private static long NANOS_IN_ONE_SECOND = 1000 * 1000 * 1000;
    40      private static int INITIAL_N = 1000;
    41      private static int LAST_N = 100;
    42      private static int SLACK_FACTOR = 3;
    43
    44      static {
    45          // let the JIT warm up
    46          computeBogoIPS(INITIAL_N);
    47          double bogo_ips = computeBogoIPS(INITIAL_N);
    48          System.out.println("Host runs at " + bogo_ips + " BIPS");
    49      }
    50
    51      /**
    52       * Compute bogoInstructions per second
    53       * <p>
    54       * on a 3.2 Ghz Pentium D CPU (around 2007), we obtain about 9'000 bogoIPS.
    55       *
    56       * @param N
    57       *                number of bogoInstructions to average over in order to
    58       *                compute the result
    59       * @return bogo Instructions Per Second
    60       */
    61      private static double computeBogoIPS(int N) {
    62          long begin = System.nanoTime();
    63
    64          for (int i = 0; i < N; i++) {
    65              bogoInstruction();
    66          }
    67          long end = System.nanoTime();
    68
    69          // duration
    70          double D = end - begin;
    71          // average duration per instruction
    72          double avgDPIS = D / N;
    73          // System.out.println(D + " nanos for " + N + " instructions");
    74          // System.out.println(avgD + " nanos per instruction");
    75
    76          double bogoIPS = NANOS_IN_ONE_SECOND / avgDPIS;
    77          // System.out.println(bogoIPS + " bogoIPS");
    78
    79          return bogoIPS;
    80      }
    81
    82      private static void bogoInstruction() {
    83          // use our own random number generator, independent of the host JDK
    84          MyRandom myRandom = new MyRandom(100);
    85          int len = 150;
    86          int[] intArray = new int[len];
    87          for (int i = 0; i < len; i++) {
    88              intArray[i] = myRandom.nextInt();
    89          }
    90          // use our own sort algorithm, independent of the host JDK
    91          BubbleSort.sort(intArray);
    92      }
    93
    94      /**
    95       * Computed the BogoIPS for this host CPU.
    96       *
    97       * @return
    98       */
    99      public static double currentBIPS() {
    100         return computeBogoIPS(LAST_N);
    101     }
    102
    103     static double min(double a, double b) {
    104         return (a <= b) ? a : b;
    105     }
    106
    107     /**
    108      * Assertion used for values that <b>decrease</b> with faster CPUs, typically
    109      * the time (duration) needed to perform a task.
    110      *
    111      * @param currentDuration
    112      * @param referenceDuration
    113      * @param referenceBIPS
    114      * @throws AssertionFailedError
    115      */
    116     public static void assertDuration(double currentDuration, long referenceDuration, double referenceBIPS) throws AssertionFailedError {
    117         double ajustedDuration = adjustExpectedDuration(referenceDuration, referenceBIPS);
    118         if (currentDuration > ajustedDuration * SLACK_FACTOR) {
    119             throw new AssertionFailedError("current duration " + currentDuration + " exceeded expected " + ajustedDuration + " (adjusted reference), "
    120                             + referenceDuration + " (raw reference)");
    121         }
    122     }
    123
    124     /**
    125      * Assertion used for values that <b>increase<b> with faster CPUs, typically
    126      * the number of operations accomplished per unit of time.
    127      *
    128      * @param currentPerformance
    129      * @param referencePerformance
    130      * @param referenceBIPS
    131      * @throws AssertionFailedError
    132      */
    133     public static void assertPerformance(double currentPerformance, long referencePerformance, double referenceBIPS) throws AssertionFailedError {
    134         double ajustedPerf = adjustExpectedPerformance(referencePerformance, referenceBIPS);
    135         if (currentPerformance * SLACK_FACTOR < ajustedPerf) {
    136             throw new AssertionFailedError(currentPerformance + " below expected " + ajustedPerf + " (adjusted), " + referencePerformance + " (raw)");
    137         }
    138     }
    139
    140     private static double adjustExpectedPerformance(long referenceDuration, double referenceBIPS) {
    141         double currentBIPS = currentBIPS();
    142         return referenceDuration * (currentBIPS / referenceBIPS);
    143     }
    144
    145     private static double adjustExpectedDuration(long referenceDuration, double referenceBIPS) {
    146         double currentBIPS = currentBIPS();
    147         System.out.println("currentBIPS=" + currentBIPS + " BIPS");
    148         return referenceDuration * (referenceBIPS / currentBIPS);
    149     }
    150 }