1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.nuiton.util;
24
25 import org.apache.commons.collections.primitives.ArrayLongList;
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.TreeMap;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class CallAnalyse {
54
55
56
57
58 private static final Log log = LogFactory.getLog(CallAnalyse.class);
59
60 static private List<ThreadStatistics> listThreadStatistics =
61 new ArrayList<ThreadStatistics>();
62
63 static private ThreadLocal<ThreadStatistics> stats =
64 new ThreadLocal<ThreadStatistics>() {
65 @Override
66 protected synchronized ThreadStatistics initialValue() {
67 ThreadStatistics result = new ThreadStatistics();
68 listThreadStatistics.add(result);
69 return result;
70 }
71 };
72
73
74
75
76 public static void activate() {
77 stats.get().setActivated(true);
78 }
79
80
81
82
83 public static void desactivate() {
84 stats.get().setActivated(false);
85 }
86
87
88
89
90
91
92 public static boolean isActivate() {
93 return stats.get().getActivated();
94 }
95
96
97
98
99 public static void enter(String name) {
100 ThreadStatistics t = stats.get();
101 if (t.getActivated()) {
102 t.get(name).enter();
103 }
104 }
105
106
107
108
109
110
111
112 public static void exit(String name) {
113 ThreadStatistics t = stats.get();
114 if (t.getActivated()) {
115 t.get(name).exit();
116 }
117 }
118
119
120
121
122 public static ThreadStatistics getThreadStatistics() {
123 return stats.get();
124 }
125
126
127
128
129 public static List<ThreadStatistics> getAllThreadStatistics() {
130 return listThreadStatistics;
131 }
132
133 public static class ThreadStatistics extends TreeMap<String, CallStatistics> {
134
135 private static final long serialVersionUID = -36051448464013504L;
136
137 protected boolean activated = false;
138
139 public boolean getActivated() {
140 return activated;
141 }
142
143 public void setActivated(boolean activated) {
144 this.activated = activated;
145 }
146
147 public CallStatistics get(String name) {
148 CallStatistics result = super.get(name);
149 if (result == null) {
150 put(name, result = new CallStatistics(name));
151 }
152 return result;
153 }
154
155 public String toString() {
156 return values().toString();
157 }
158 }
159
160
161
162
163
164
165
166
167 public static Map<String, CallStatisticsSummary> getSummary() {
168 Map<String, CallStatisticsSummary> results = new HashMap<String, CallStatisticsSummary>();
169 for (ThreadStatistics stats : CallAnalyse.getAllThreadStatistics()) {
170 for (String name : stats.keySet()) {
171 CallStatisticsSummary stat = results.get(name);
172 if (stat == null) {
173 stat = new CallStatisticsSummary(name);
174 results.put(name, stat);
175 }
176 stat.addCallStats(stats.get(name));
177 }
178 }
179 return results;
180 }
181
182
183
184
185
186
187
188
189 public static class CallStatistics implements Cloneable {
190 protected String name = null;
191
192 protected long calls = 0;
193
194 protected long minTime = Long.MAX_VALUE;
195
196 protected long maxTime = Long.MIN_VALUE;
197
198 protected long sumTime = 0;
199
200 protected long minMemory = Long.MAX_VALUE;
201
202 protected long maxMemory = Long.MIN_VALUE;
203
204 protected long sumMemory = 0;
205
206
207
208
209 protected ArrayLongList times = new ArrayLongList();
210
211 protected ArrayLongList memories = new ArrayLongList();
212
213 protected Runtime runtime = Runtime.getRuntime();
214
215 public CallStatistics(String name) {
216 this.name = name;
217 }
218
219 public void enter() {
220 times.add(System.nanoTime());
221 memories.add(getMemory());
222 }
223
224 public void exit() {
225 calls++;
226
227 if (times.size() == 0) {
228 log.info("To many exit call for " + name);
229 return;
230 }
231 long time = times.removeElementAt(times.size() - 1);
232 time = System.nanoTime() - time;
233 if (time < minTime || minTime == Long.MAX_VALUE) {
234 minTime = time;
235 }
236 if (time > maxTime) {
237 maxTime = time;
238 }
239 sumTime += time;
240
241 long memory = memories.removeElementAt(memories.size() - 1);
242 memory = getMemory() - memory;
243 if (memory < minMemory || minMemory == Long.MAX_VALUE) {
244 minMemory = memory;
245 }
246 if (memory > maxMemory) {
247 maxMemory = memory;
248 }
249 sumMemory += memory;
250 }
251
252 public String getName() {
253 return name;
254 }
255
256 public long getCalls() {
257 return calls;
258 }
259
260 public long getMinTime() {
261 return minTime;
262 }
263
264 public long getMaxTime() {
265 return maxTime;
266 }
267
268 public long getSumTime() {
269 return sumTime;
270 }
271
272 public long getAvgTime() {
273 if (calls == 0) {
274 return 0;
275 } else {
276 return sumTime / calls;
277 }
278 }
279
280 public long getMinMemory() {
281 return minMemory;
282 }
283
284 public long getMaxMemory() {
285 return maxMemory;
286 }
287
288 public long getSumMemory() {
289 return sumMemory;
290 }
291
292 public long getAvgMemory() {
293 if (calls == 0) {
294 return 0;
295 } else {
296 return sumMemory / calls;
297 }
298 }
299
300 protected long getMemory() {
301
302 return runtime.totalMemory() - runtime.freeMemory();
303 }
304
305 @Override
306 public String toString() {
307 return getName() + " calls=" + getCalls()
308 + " time=" + StringUtil.convertTime(getSumTime())
309 + "(" + StringUtil.convertTime(getMinTime()) + "/" + StringUtil.convertTime(getAvgTime()) + "/" + StringUtil.convertTime(getMaxTime()) + ")"
310 + " memory=" + StringUtil.convertMemory(getSumMemory())
311 + "(" + StringUtil.convertMemory(getMinMemory()) + "/" + StringUtil.convertMemory(getAvgMemory()) + "/" + StringUtil.convertMemory(getMaxMemory()) + ")"
312 ;
313 }
314
315 }
316
317
318
319
320
321
322
323 public static class CallStatisticsSummary extends CallStatistics {
324
325 public CallStatisticsSummary(String name) {
326 super(name);
327 }
328
329
330
331
332
333
334
335 public void addCallStats(CallStatistics other) {
336 if (other == null || this.equals(other)) {
337 return;
338 }
339 calls += other.getCalls();
340 if (other.getMinTime() < minTime || minTime == Long.MAX_VALUE) {
341 minTime = other.getMinTime();
342 }
343 if (other.getMaxTime() > maxTime) {
344 maxTime = other.getMaxTime();
345 }
346
347 sumTime += other.getSumTime();
348
349 if (other.getMinMemory() < minMemory || minMemory == Long.MAX_VALUE) {
350 minMemory = other.getMinMemory();
351 }
352 if (other.getMaxMemory() > maxMemory) {
353 maxMemory = other.getMaxMemory();
354 }
355 sumMemory += other.getSumMemory();
356 }
357 }
358
359 }
360