View Javadoc

1   /*
2    * Copyright 2005 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at 
7    * 
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software 
11   * distributed under the License is distributed on an "AS IS" BASIS, 
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License.
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      // a method's timing descriptor
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      // a method call's timing descriptor
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      // output device
71      PrintWriter out = new PrintWriter(System.out, true);
72  
73      // methods
74      HashMap methods = new HashMap();
75  
76      // method call stack
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          // get time
97          final long now = System.currentTimeMillis();
98  
99          // get a method descriptor
100         MethodDescriptor current = (MethodDescriptor)methods.get(name);
101         if (current == null) {
102             current = new MethodDescriptor(name);
103             methods.put(name, current);
104         }
105 
106         // update method descriptor
107         current.calls++;
108         current.instantiations++;
109 
110         // update method call stack
111         calls.add(new MethodCall(current, message, now, now));
112     }
113 
114     public final synchronized void pop()
115     {
116         // get time
117         final long now = System.currentTimeMillis();
118 
119         // update method call stack
120         final MethodCall call = (MethodCall)calls.remove(calls.size()-1);
121 
122         // get current call's time
123         final long currentSelf = now - call.self;
124         final long currentTotal = now - call.total;
125 
126         // update previous call's self time
127         if (calls.size() > 0) {
128             final MethodCall previous = (MethodCall)calls.get(calls.size()-1);
129             previous.self += currentTotal;
130         }
131 
132         // update method descriptor
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         //nf.applyPattern("#,##0.00");
176         //out.println("Timer : pattern = " + nf.toPattern());
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 }