1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.jdo.impl.enhancer.util;
20
21 import java.util.HashMap;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Comparator;
25
26 import java.text.DecimalFormat;
27
28 import java.io.PrintWriter;
29
30
31 /***
32 * Utility class for simple performance analysis.
33 */
34 public final class Timer
35 {
36
37 static private class MethodDescriptor
38 {
39 final String name;
40 int instantiations;
41 int calls;
42 long self;
43 long total;
44
45 MethodDescriptor(String name)
46 {
47 this.name = name;
48 }
49 }
50
51
52 static private class MethodCall
53 {
54 final MethodDescriptor method;
55 final String message;
56 long self;
57 long total;
58
59 MethodCall(MethodDescriptor method,
60 String message,
61 long self,
62 long total)
63 {
64 this.method = method;
65 this.message = message;
66 this.self = self;
67 this.total = total;
68 }
69 }
70
71
72 PrintWriter out = new PrintWriter(System.out, true);
73
74
75 HashMap methods = new HashMap();
76
77
78 private final ArrayList calls = new ArrayList(16);
79
80 public Timer()
81 {
82 this.out = out;
83 }
84
85 public Timer(PrintWriter out)
86 {
87 this.out = out;
88 }
89
90 public final synchronized void push(String name)
91 {
92 push(name, name);
93 }
94
95 public final synchronized void push(String name, String message)
96 {
97
98 final long now = System.currentTimeMillis();
99
100
101 MethodDescriptor current = (MethodDescriptor)methods.get(name);
102 if (current == null) {
103 current = new MethodDescriptor(name);
104 methods.put(name, current);
105 }
106
107
108 current.calls++;
109 current.instantiations++;
110
111
112 calls.add(new MethodCall(current, message, now, now));
113 }
114
115 public final synchronized void pop()
116 {
117
118 final long now = System.currentTimeMillis();
119
120
121 final MethodCall call = (MethodCall)calls.remove(calls.size()-1);
122
123
124 final long currentSelf = now - call.self;
125 final long currentTotal = now - call.total;
126
127
128 if (calls.size() > 0) {
129 final MethodCall previous = (MethodCall)calls.get(calls.size()-1);
130 previous.self += currentTotal;
131 }
132
133
134 final MethodDescriptor current = call.method;
135 current.self += currentSelf;
136 if (--current.instantiations == 0) {
137 current.total += currentTotal;
138 }
139
140 if (false) {
141 out.println("Timer (n,g): " + call.message + " : ("
142 + currentSelf + ", " + currentTotal + ")");
143 }
144 }
145
146 static private final String pad(String s, int i)
147 {
148 StringBuffer b = new StringBuffer();
149 for (i -= s.length(); i > 0; i--)
150 b.append((char)' ');
151 b.append(s);
152 return b.toString();
153 }
154
155 public final synchronized void print()
156 {
157 out.println("Timer : printing accumulated times ...");
158 final Object[] calls = methods.values().toArray();
159
160 Arrays.sort(calls,
161 new Comparator() {
162 public int compare(Object o1,
163 Object o2) {
164 return (int)(((MethodDescriptor)o2).total
165 - ((MethodDescriptor)o1).total);
166 }
167 public boolean equals(Object obj) {
168 return (compare(this, obj) == 0);
169 }
170 });
171
172 out.println("Timer : total s self s #calls name");
173 DecimalFormat nf = new DecimalFormat();
174 nf.setMaximumFractionDigits(2);
175 nf.setMinimumFractionDigits(2);
176
177
178 for (int i = 0; i < calls.length; i++) {
179 final MethodDescriptor current = (MethodDescriptor)calls[i];
180
181 out.println("Timer : "
182 + pad(nf.format(current.total / 1000.0), 8) + " "
183 + pad(nf.format(current.self / 1000.0), 8) + " "
184 + pad(String.valueOf(current.calls), 6) + " "
185 + current.name);
186 }
187 }
188 }