KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sape > carbon > services > perflog > BoundedBufferPerformanceLogger


1 /*
2  * The contents of this file are subject to the Sapient Public License
3  * Version 1.0 (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://carbon.sf.net/License.html.
6  *
7  * Software distributed under the License is distributed on an "AS IS" basis,
8  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9  * the specific language governing rights and limitations under the License.
10  *
11  * The Original Code is The Carbon Component Framework.
12  *
13  * The Initial Developer of the Original Code is Sapient Corporation
14  *
15  * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
16  */

17
18 package org.sape.carbon.services.perflog;
19
20 import java.util.Collections JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import org.sape.carbon.core.component.ComponentConfiguration;
26 import org.sape.carbon.core.component.lifecycle.Configurable;
27
28 /**
29  * <p>This extension on the basic performance logger provides the additional
30  * capability to track timings over a period of time and get report on their
31  * minimums, maximum, averages and standard deviations. This implementation
32  * uses a rolling, array-based bounded buffer to store up to the last "n"
33  * timings.</p>
34  *
35  * Copyright 2003 Sapient
36  * @since carbon 1.2
37  * @author Greg Hinkle, January 2003
38  * @version $Revision: 1.6 $($Author: dvoet $ / $Date: 2003/05/05 21:21:30 $)
39  */

40 public class BoundedBufferPerformanceLogger
41 extends DefaultPerformanceLogger
42 implements ReportingPerformanceLogger, Configurable {
43
44
45     /**
46      * A synchronized map of TimingInfo objects to the tracked object
47      */

48     protected Map JavaDoc timingMap = Collections.synchronizedMap(new HashMap JavaDoc());
49
50     /**
51      * Holds the number of timings to track for statistics generation.
52      */

53     protected int trackedTimings;
54
55     /**
56      * This implementation adds additional steps to track a set of timings
57      * in order to calculate statistics on the executions.
58      *
59      * @param trackedObject the object that is being timed
60      * @param time the duration of the execution to track
61      */

62     protected void trackTiming(Object JavaDoc trackedObject, long time) {
63         super.trackTiming(trackedObject, time);
64         registerTiming(trackedObject, time);
65     }
66
67     /**
68      * This implementation will add a new TimingInfo object to the main tracking
69      * map if one is not found corresponding to the tracked action. It will
70      * then register the supplied timing with that object.
71      *
72      * @param trackedObject the object being tracked
73      * @param time the time tracked of the call
74      */

75     protected void registerTiming(Object JavaDoc trackedObject, long time) {
76
77         // Warning: Known non-synchronization
78
// Sacrificing data to maintain speed of logging
79
// (may loose the first few timings)
80
TimingInfo timingInfo =
81             (TimingInfo) this.timingMap.get(trackedObject);
82
83         if (timingInfo == null) {
84             timingInfo = new TimingInfo(trackedObject, this.trackedTimings);
85
86             this.timingMap.put(trackedObject, timingInfo);
87         }
88         timingInfo.addTiming(time);
89     }
90
91     /**
92      * Holds the characters used to pad in the pad method.
93      *
94      * @see #pad
95      */

96     private static final String JavaDoc PAD = " ";
97
98     /**
99      * Pads the information fields to a fixed length for display.
100      *
101      * @param str the string to pad
102      * @param len the max length to pad to
103      * @return a new padded version of the string
104      */

105     private String JavaDoc pad(String JavaDoc str, int len) {
106         if (str.length() > len) {
107             return str.substring(0, len - 1) + " ";
108         } else {
109             return str + PAD.substring(0, len - str.length());
110         }
111     }
112
113     /**
114      * Returns a string report of timings that are being tracked by this
115      * perfomance logger.
116      *
117      * @return A report of information for this logger
118      */

119     public String JavaDoc getReport() {
120         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(1000);
121         buf.append("Extended performance logger report [");
122         buf.append(this.timingMap.size());
123         buf.append("] items.\n");
124
125         buf.append("Min Max Avg StdDev Tracked Object\n");
126         Iterator JavaDoc iter = this.timingMap.values().iterator();
127         while (iter.hasNext()) {
128             TimingInfo info = (TimingInfo) iter.next();
129
130             buf.append(pad(String.valueOf(info.getMin()), 10));
131             buf.append(pad(String.valueOf(info.getMax()), 10));
132             buf.append(pad(String.valueOf(info.getAverage()), 10));
133             buf.append(pad(String.valueOf(info.getStandardDeviation()), 10));
134             buf.append(String.valueOf(info.getTrackedObject()));
135             buf.append("\n");
136         }
137         return buf.toString();
138     }
139
140     /**
141      * Configure the component. This is preceded and followed by the suspend
142      * and resume operations if they are available on the component.
143      *
144      * @param configuration BoundedBufferPerformanceLoggerConfiguration to
145      * configure this component
146      * @throws org.sape.carbon.core.component.lifecycle.LifecycleException
147      */

148     public void configure(ComponentConfiguration configuration) {
149
150         this.trackedTimings =
151             ((BoundedBufferPerformanceLoggerConfiguration) configuration).
152                 getTrackedTimingsCount();
153     }
154
155     /**
156      * <p>This inner class supports the tracking of timings on a
157      * single tracked item. It stores the item to be tracked as well
158      * as a array-based bounded buffer. This buffer of configurable
159      * size stores the last n timings for use in determing rolling
160      * averages for the timings as well as standard deviation.</p>
161      *
162      * <p>The provided minimum and maximum values are calculated
163      * for all timings regardless of whether they are within the
164      * bounded-buffer at a given point in time.</p>
165      */

166     public static class TimingInfo {
167         /** Holds the object being tracked. */
168         private Object JavaDoc trackedObject;
169
170         /** Holds the size of the timingArray. */
171         private int capacity;
172
173         /** Indicates if the timingArray is full. */
174         private boolean full = false;
175
176         /** Holds the timings for the method. */
177         private long[] timingArray;
178
179         /**
180          * Holds the current index for the new timing. The index
181          * wraps around back to zero after reaching the capacity and
182          * replaces old values.
183          */

184         private int index;
185
186         /** Holds the min time taken. */
187         private long min = Long.MAX_VALUE;
188
189         /** Holds the max time taken. */
190         private long max;
191
192         /**
193          * Creates a new timing info object for the specified tracked object
194          * of the specified size.
195          *
196          * @param trackedObject The object to be tracked.
197          * @param capacity the number of timings that will be tracked.
198          */

199         public TimingInfo(Object JavaDoc trackedObject, int capacity) {
200             this.trackedObject = trackedObject;
201             this.timingArray = new long[capacity];
202             this.capacity = capacity;
203         }
204
205         /**
206          * Retrieves the object being tracked.
207          *
208          * @return the object being tracked
209          */

210         public Object JavaDoc getTrackedObject() {
211             return this.trackedObject;
212         }
213
214         /**
215          * Adds a new timing into the statistics.
216          *
217          * @param time the length of time of the method call
218          */

219         public synchronized void addTiming(long time) {
220             this.timingArray[index++] = time;
221             if (this.index >= this.capacity) {
222                 this.index = 0;
223                 this.full = true;
224             }
225
226             if (this.max < time) {
227                 this.max = time;
228             }
229
230             if (this.min > time) {
231                 this.min = time;
232             }
233         }
234
235         /**
236          * Returns the mininum time taken.
237          *
238          * @return the min time taken
239          */

240         public long getMin() {
241             return this.min;
242         }
243
244         /**
245          * Returns the max time taken.
246          *
247          * @return max time taken
248          */

249         public long getMax() {
250             return this.max;
251         }
252
253         /**
254          * Returns the amount of timings stored in the object.
255          *
256          * @return amount of timings stored in the object
257          */

258         public synchronized int size() {
259             if (full) {
260                 return this.capacity;
261             } else {
262                 return this.index;
263             }
264         }
265
266         /**
267          * Calcluate standard deviation in timings using Knuth's algorithm.
268          *
269          * @return standard deviation
270          */

271         public synchronized double getStandardDeviation() {
272             final int n = size();
273             if (n < 2) {
274                 return Double.NaN;
275             }
276
277             double avg = this.timingArray[0];
278             double sum = 0;
279             for (int i = 1; i < n - 1; i++) {
280                 double newavg = avg + (this.timingArray[i] - avg) / (i + 1);
281                 sum += (this.timingArray[i] - avg)
282                        * (this.timingArray[i] - newavg);
283
284                 avg = newavg;
285             }
286             return Math.sqrt (sum / (n - 1));
287         }
288
289         /**
290          * Calculates the average time of the calls.
291          *
292          * @return the average time of the calls.
293          */

294         public synchronized double getAverage() {
295             final int n = size();
296             double sum = 0;
297             for (int i = 0; i < n; i++) {
298                 sum += this.timingArray[i];
299             }
300             return (sum / (double) n);
301         }
302     }
303 }
Popular Tags