1 /* ==========================================
2 * JperfProbe : Java Performance Probes
3 * ==========================================
4 *
5 * Project Info: http://jperfprobe.sourceforge.net/
6 * Project Lead: Tor-Erik Larsen (http://sourceforge.net/users/uptime62)
7 *
8 * (C) Copyright 2005, by Tor-Erik Larsen and Contributors.
9 *
10 * This library is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this library; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
23 */
24 package net.sf.jperfprobe;
25
26 import org.slf4j.*;
27
28 import java.io.*;
29 import java.util.*;
30 import java.util.concurrent.locks.*;
31
32 /**
33 * The ProbeManager is the probe factory. It makes it possible start start and stop a probe.
34 * The probe can be started in different ways:<br><br>
35 * <p/>
36 * 1. Start and stop from same scope, same thread, via probe name<br>
37 * 2. Start probes multithreaded from same scope, via probe name<br>
38 * 3. Start in one scope and stop in another scope singlethreaded via probe name<br>
39 * 4. Start in one scope and stop in another scope multithreaded via probe instance<br>
40 */
41
42 public final class ProbeManagerImpl implements Serializable, ProbeManager {
43 final Logger log = LoggerFactory.getLogger(ProbeManagerImpl.class);
44
45
46 /**
47 * presentation unit enum
48 */
49 public static enum Presentation {
50 SECONDS(1000000000.0d, "s"),
51 MILLIS(1000000.0d, "ms"),
52 MICROS(1000.0d, "us"),
53 NANOS(1.0d, "ns");
54
55 private final double timeFactor;
56 private final String unit;
57
58 Presentation(double timeFactor, String u) {
59 this.timeFactor = timeFactor;
60 this.unit = u;
61 }
62
63 /**
64 * Get the time factor for a presentation
65 *
66 * @return
67 */
68 public double getTimeFactor() {
69 return timeFactor;
70 }
71
72 /**
73 * Get unit as string
74 *
75 * @return
76 */
77 /*
78 public String getUnit() {
79 return unit;
80 }
81 */
82 }
83
84 private Presentation presentation = Presentation.NANOS;
85
86 private int firstSamplesToSkip;
87
88 // map containing all created results
89 private final Map<String, Result> resultMap = new HashMap<String, Result>();
90
91 private final ReentrantReadWriteLock rmapRwl = new ReentrantReadWriteLock();
92 private final Lock rLock = rmapRwl.readLock();
93 private final Lock wLock = rmapRwl.writeLock();
94
95
96 private Time time = TimeFactory.getTime();
97
98 /**
99 * Constructor of probe
100 */
101 public ProbeManagerImpl() {
102 }
103
104
105 /**
106 * Constr
107 *
108 * @param firstSamplesToSkip, samples to skip before recording
109 * @param presentation, of measured values
110 * @param time, the time implementation to use
111 */
112 public ProbeManagerImpl(int firstSamplesToSkip, Presentation presentation, Time time) {
113 this.firstSamplesToSkip = firstSamplesToSkip;
114 this.presentation = presentation;
115 this.time = time;
116 }
117
118 /**
119 * Put a probe into the manager, if the probe exist it will be overwritten. This makes it possible
120 * to create a Probe outside the ProbeManager and insert it later.
121 *
122 * @param probeName
123 * @param probe
124 */
125 public void put(String probeName, Probe probe) {
126 getResult(probeName).addprobe(probe);
127 }
128
129
130 /**
131 * Get a result for a given probe
132 *
133 * @param probeName
134 * @return Result
135 */
136 public Result getResult(String probeName) {
137 Result result;
138
139 synchronized (resultMap) {
140 result = resultMap.get(probeName);
141
142 if (result == null) {
143 result = new Result(firstSamplesToSkip, probeName);
144 resultMap.put(probeName, result);
145 }
146 }
147
148 return result;
149 }
150
151 /**
152 * Get all the results
153 *
154 * @return
155 */
156 public Collection<Result> getResults() {
157 return resultMap.values();
158 }
159
160 /**
161 * Get instance of a named probe, if it is non existent, a default probe will be created.
162 * And time will be set to null.
163 *
164 * @param probeName identifying name of probe
165 * @return probe, null if it cant look it up
166 */
167 public Probe getProbeInstance(String probeName) {
168 Result result = getResult(probeName);
169
170 Probe probe;
171 synchronized (result) {
172 probe = result.getProbe();
173
174 if (probe == null) {
175 probe = new DefaultProbe(probeName, time);
176 result.addprobe(probe);
177 }
178 }
179
180 return probe;
181 }
182
183 /**
184 * Start probe, identified by probeName, if the probe does not exist, it will be created.
185 *
186 * @param probeName name of existing or new probe.
187 */
188 public Probe start(String probeName) {
189 Probe p = getProbeInstance(probeName);
190 p.start();
191
192 return p;
193 }
194
195 public Probe startSingle(String probeName) {
196 Result result = getResult(probeName);
197 Probe probe = result.getSingleProbe();
198
199 if (probe == null) {
200 probe = new DefaultProbe(probeName, time);
201 result.setSingleProbe(probe);
202 }
203
204 probe.start();
205
206 return probe;
207 }
208
209 /**
210 * Stop timing. If its non existent, no time or sample will be registered.
211 *
212 * @param probeName name of probe to stop
213 */
214 public void stop(String probeName) {
215 Result result = getResult(probeName);
216
217 Probe probe = result.getSingleProbe();
218 synchronized (result) {
219 if (probe == null) {
220 probe = result.getProbe();
221 if (probe == null) {
222 return;
223 }
224 }
225 probe.stop();
226 result.addSample(probe.getElapsed());
227 }
228
229 }
230
231 /**
232 * Add a sample from a probe. The probe does not need to be managed by ProbeManager
233 *
234 * @param p
235 */
236 public void addSampleFromProbe(Probe p) {
237 Result r = getResult(p.getName());
238 r.addSample(p.getElapsed());
239 }
240
241 /**
242 * Clear the result for a named probe
243 *
244 * @param probeName
245 */
246 public void clear(String probeName) {
247 getResult(probeName).clear();
248 }
249
250 /**
251 * Clear the results for all probes
252 */
253 public void clear() {
254 for (Result r : resultMap.values()) {
255 r.clear();
256 }
257 // should we really do this, the results could stay
258 resultMap.clear();
259 }
260
261 /**
262 * Disable a named probe
263 * @param probeName
264 */
265 public void disable(String probeName) {
266 getResult(probeName).disable();
267 }
268
269 /**
270 * Disable all probes.
271 */
272 public void disable() {
273 for (Result r : resultMap.values()) {
274 r.disable();
275 }
276 }
277
278 public void enable(String probeName) {
279 getResult(probeName).enable();
280 }
281
282 /**
283 * Enable all probes.
284 */
285 public void enable() {
286 for (Result r : resultMap.values()) {
287 r.enable();
288 }
289 }
290
291 /**
292 * Set the presentation unit for presentation.
293 *
294 * @param p presentation to set
295 */
296 public void setPresentation(Presentation p) {
297 presentation = p;
298 }
299
300
301 public int getFirstSamplesToSkip() {
302 return firstSamplesToSkip;
303 }
304
305 /**
306 * Set how many samples to skip in the calculation of statistics. If set to ie. 5, the first 5 samples will
307 * not be taken into account when calculating max/min/n#samples and average.
308 *
309 * @param _firstSamplesToSkip
310 */
311 public void setFirstSamplesToSkip(int _firstSamplesToSkip) {
312 firstSamplesToSkip = _firstSamplesToSkip;
313 }
314
315 /**
316 * Get the current presentation for the manager
317 *
318 * @return presentation
319 */
320 public Presentation getPresentation() {
321 return presentation;
322 }
323
324 /**
325 * Set the Time implementation.
326 *
327 * @param tim
328 */
329 public void setTime(Time tim) {
330 time = tim;
331 }
332
333 public Time getTime() {
334 return this.time;
335 }
336
337 /**
338 * Get result as a string
339 *
340 * @param probe
341 * @return result
342 */
343 public String toString(String probe) {
344 Result p = getResult(probe);
345
346 return "probe name=" + probe + ", #samples=" + p.getNSamples() + ", total=" + p.getTotal()
347 / presentation.getTimeFactor() + " , average=" + p.getAverage() / presentation.getTimeFactor()
348 + " , max=" + p.getMax() / presentation.getTimeFactor() + " , min=" + p.getMin()
349 / presentation.getTimeFactor() + " , units=" + presentation;
350 }
351
352 /**
353 * Get all samples from a probe, as a string newline delimited
354 *
355 * @param probe
356 * @return samples
357 */
358 public long[] getSamples(String probe) {
359 return getResult(probe).getSamples();
360 }
361
362 /**
363 * Get all probe names in the ProbeManager
364 *
365 * @return probename
366 */
367 public String[] getNames() {
368 Set<String> names = resultMap.keySet();
369 String[] ret = new String[names.size()];
370
371 return names.toArray(ret);
372 }
373 }