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