Home | History | Annotate | Download | only in helpers
      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ülcü
     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 }
    151