001/** 002 * Copyright (c) 2004-2011 QOS.ch 003 * All rights reserved. 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining 006 * a copy of this software and associated documentation files (the 007 * "Software"), to deal in the Software without restriction, including 008 * without limitation the rights to use, copy, modify, merge, publish, 009 * distribute, sublicense, and/or sell copies of the Software, and to 010 * permit persons to whom the Software is furnished to do so, subject to 011 * the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be 014 * included in all copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 021 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 023 * 024 */ 025package org.slf4j.helpers; 026 027import junit.framework.AssertionFailedError; 028 029/** 030 * BogoPerf is used to check that the time required to perform a certain 031 * operation does not deteriorate over time. BogoPerf adjusts to the CPU speed 032 * and capabilities of the host. 033 * 034 * @author Ceki Gülcü 035 * 036 */ 037public class BogoPerf { 038 039 private static long NANOS_IN_ONE_SECOND = 1000 * 1000 * 1000; 040 private static int INITIAL_N = 1000; 041 private static int LAST_N = 100; 042 private static int SLACK_FACTOR = 3; 043 044 static { 045 // let the JIT warm up 046 computeBogoIPS(INITIAL_N); 047 double bogo_ips = computeBogoIPS(INITIAL_N); 048 System.out.println("Host runs at " + bogo_ips + " BIPS"); 049 } 050 051 /** 052 * Compute bogoInstructions per second 053 * <p> 054 * on a 3.2 Ghz Pentium D CPU (around 2007), we obtain about 9'000 bogoIPS. 055 * 056 * @param N 057 * number of bogoInstructions to average over in order to 058 * compute the result 059 * @return bogo Instructions Per Second 060 */ 061 private static double computeBogoIPS(int N) { 062 long begin = System.nanoTime(); 063 064 for (int i = 0; i < N; i++) { 065 bogoInstruction(); 066 } 067 long end = System.nanoTime(); 068 069 // duration 070 double D = end - begin; 071 // average duration per instruction 072 double avgDPIS = D / N; 073 // System.out.println(D + " nanos for " + N + " instructions"); 074 // System.out.println(avgD + " nanos per instruction"); 075 076 double bogoIPS = NANOS_IN_ONE_SECOND / avgDPIS; 077 // System.out.println(bogoIPS + " bogoIPS"); 078 079 return bogoIPS; 080 } 081 082 private static void bogoInstruction() { 083 // use our own random number generator, independent of the host JDK 084 MyRandom myRandom = new MyRandom(100); 085 int len = 150; 086 int[] intArray = new int[len]; 087 for (int i = 0; i < len; i++) { 088 intArray[i] = myRandom.nextInt(); 089 } 090 // use our own sort algorithm, independent of the host JDK 091 BubbleSort.sort(intArray); 092 } 093 094 /** 095 * Computed the BogoIPS for this host CPU. 096 * 097 * @return 098 */ 099 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}