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,
117 long referenceDuration, double referenceBIPS) throws AssertionFailedError {
118 double ajustedDuration = adjustExpectedDuration(referenceDuration,
119 referenceBIPS);
120 if (currentDuration > ajustedDuration * SLACK_FACTOR) {
121 throw new AssertionFailedError("current duration " + currentDuration
122 + " exceeded expected " + ajustedDuration + " (adjusted reference), "
123 + referenceDuration + " (raw reference)");
124 }
125 }
126
127 /**
128 * Assertion used for values that <b>increase<b> with faster CPUs, typically
129 * the number of operations accomplished per unit of time.
130 *
131 * @param currentPerformance
132 * @param referencePerformance
133 * @param referenceBIPS
134 * @throws AssertionFailedError
135 */
136 public static void assertPerformance(double currentPerformance,
137 long referencePerformance, double referenceBIPS)
138 throws AssertionFailedError {
139 double ajustedPerf = adjustExpectedPerformance(referencePerformance,
140 referenceBIPS);
141 if (currentPerformance * SLACK_FACTOR < ajustedPerf) {
142 throw new AssertionFailedError(currentPerformance + " below expected "
143 + ajustedPerf + " (adjusted), " + referencePerformance + " (raw)");
144 }
145 }
146
147 private static double adjustExpectedPerformance(long referenceDuration,
148 double referenceBIPS) {
149 double currentBIPS = currentBIPS();
150 return referenceDuration * (currentBIPS / referenceBIPS);
151 }
152
153 private static double adjustExpectedDuration(long referenceDuration,
154 double referenceBIPS) {
155 double currentBIPS = currentBIPS();
156 System.out.println("currentBIPS=" + currentBIPS + " BIPS");
157 return referenceDuration * (referenceBIPS / currentBIPS);
158 }
159 }