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 */ computeBogoIPS(int N)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 bogoInstruction()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 */ currentBIPS()99 public static double currentBIPS() { 100 return computeBogoIPS(LAST_N); 101 } 102 min(double a, double b)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 */ assertDuration(double currentDuration, long referenceDuration, double referenceBIPS)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 */ assertPerformance(double currentPerformance, long referencePerformance, double referenceBIPS)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 adjustExpectedPerformance(long referenceDuration, double referenceBIPS)140 private static double adjustExpectedPerformance(long referenceDuration, double referenceBIPS) { 141 double currentBIPS = currentBIPS(); 142 return referenceDuration * (currentBIPS / referenceBIPS); 143 } 144 adjustExpectedDuration(long referenceDuration, double referenceBIPS)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