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
25 package net.sf.jperfprobe;
26
27 import org.slf4j.*;
28
29 import java.io.*;
30 import java.util.*;
31
32
33 /**
34 * Class Result.
35 * A Result contains the statistics. All calculations are done in this class.
36 * There can be multiple probes in a Result identified by the Probes threadname.
37 *
38 * @author Tor-Erik Larsen
39 * Date: 01.feb.2007
40 * Time: 10:48:56
41 */
42 public class Result implements Serializable {
43 final Logger log = LoggerFactory.getLogger(Result.class);
44
45 private int samplesToSkip;
46
47 private int currentSamplesSkip;
48 /**
49 * default maximum number of samples stored in a probe.
50 */
51 static int DEFAULT_MAXSAMPLES = 300;
52 // list of the last max samples, the oldest samples will be removed.
53 private long[] samples = new long[DEFAULT_MAXSAMPLES];
54
55 final transient private Map<String, Probe> probeMap = new HashMap<String, Probe>();
56
57 // current number of samples in this probe.
58 private int nSamples;
59
60 // index of the current sample
61 private int sampleIndex;
62
63 // maximum registered time sample in probe.
64 private double max;
65
66 // minimum registered time sample in probe.
67 private double min;
68
69 // average time calculated in this probe, based on all recorded samples, even the discarded ones,
70 // more than DEFAULT_MAXSAMPLES.
71 private double average;
72
73 // name of Result.
74 private final String name;
75
76 private long lastSample;
77
78 private Probe singleProbe;
79
80 private long total;
81
82 private double squareSum;
83
84
85 Result(String name) {
86 this.name = name;
87 }
88
89 Result(int nSkip, String name) {
90 this.samplesToSkip = nSkip;
91 this.name = name;
92 }
93
94 public long[] getSamples() {
95 long[] dest = new long[sampleIndex];
96 System.arraycopy(samples, 0, dest, 0, sampleIndex);
97
98 return dest;
99 }
100
101 public int getNSamples() {
102 return nSamples;
103 }
104
105 /*
106 int getSampleIndex() {
107 return sampleIndex;
108 }
109 */
110
111 public double getMax() {
112 return max;
113 }
114
115 public double getMin() {
116 return min;
117
118 }
119
120 public double getAverage() {
121 return average;
122 }
123
124 /**
125 * Get the sample standard deviation
126 *
127 * @return
128 */
129 public double getStdev() {
130 double nMinus1 = (nSamples <= 1) ? 1 : nSamples - 1;
131 double numerator = squareSum - ((total * total) / nSamples);
132
133 return java.lang.Math.sqrt(numerator / nMinus1);
134 }
135
136 /**
137 * Get the probe for the calling thread
138 * @return
139 */
140 Probe getProbe() {
141 return probeMap.get(Thread.currentThread().getName());
142 }
143
144
145 /**
146 * Add a probe to Result
147 *
148 * @param probe
149 */
150 void addprobe(Probe probe) {
151 synchronized (probeMap) {
152 probeMap.put(Thread.currentThread().getName(), probe);
153 }
154 }
155
156 /**
157 * Clear the map of probes and all values (max, min, samples, average...) all the probes will be removed
158 */
159 public void clear() {
160 probeMap.clear();
161 max = 0.0;
162 min = 0.0;
163 sampleIndex = 0;
164 nSamples = 0;
165 average = 0.0;
166 samples = new long[DEFAULT_MAXSAMPLES];
167 total = 0;
168
169 }
170
171 public void disable() {
172 for (Probe p : probeMap.values()) {
173 p.disable();
174 }
175 }
176
177 public void enable() {
178 for (Probe p : probeMap.values()) {
179 p.enable();
180 }
181 }
182
183
184 public String getName() {
185 return name;
186 }
187
188 /*
189 public void addSample(Probe p) {
190 addSample(p.getElapsed());
191 }
192 */
193
194 /**
195 * Add a sample to the probe, and recalculate the average & min/max values.
196 *
197 * @param time sample to add
198 */
199 public void addSample(long time) {
200 if (currentSamplesSkip < samplesToSkip) {
201 currentSamplesSkip++;
202 } else {
203 lastSample = time;
204 if (sampleIndex >= DEFAULT_MAXSAMPLES) {
205 // rollover
206 sampleIndex = 0;
207 }
208
209 samples[sampleIndex++] = time;
210 total += time;
211 average = (average * (double) nSamples + (double) time) / (double) ++nSamples;
212 squareSum += time * time;
213
214 if (time > max) {
215 max = time;
216 }
217 if (nSamples > 1) {
218 if (time < min) {
219 min = time;
220 }
221 } else {
222 min = time;
223 }
224 }
225 }
226
227 /**
228 * Get the singleprobe, there is then only one instance of a probe
229 *
230 * @return
231 */
232 public Probe getSingleProbe() {
233 return singleProbe;
234 }
235
236 public void setSingleProbe(Probe singleProbe) {
237 this.singleProbe = singleProbe;
238 }
239
240 /**
241 * Get the last sample from the probe
242 *
243 * @return
244 */
245 public long getLastSample() {
246 return lastSample;
247 }
248
249 public long getTotal() {
250 return total;
251 }
252
253 /**
254 * Get all info from result to string
255 *
256 * @return string with all result info
257 */
258 @Override
259 public String toString() {
260 return "probe name=" + name + ", #samples=" + nSamples + " , average=" + average + " , stdev=" + getStdev() + " ,max=" + max + " , min=" + min;
261 }
262 }