001: /**
002: * Copyright (C) 2001-2004 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.speedo.generation.start;
018:
019: import java.util.HashMap;
020: import java.util.ArrayList;
021: import java.util.Arrays;
022: import java.util.Comparator;
023:
024: import java.text.DecimalFormat;
025:
026: import java.io.PrintWriter;
027:
028: /**
029: * Utility class for simple performance analysis.
030: */
031: public final class Timer {
032: // a method's timing descriptor
033: static private class MethodDescriptor {
034: final String name;
035: int instantiations;
036: int calls;
037: long self;
038: long total;
039:
040: MethodDescriptor(String name) {
041: this .name = name;
042: }
043: }
044:
045: // a method call's timing descriptor
046: static private class MethodCall {
047: final MethodDescriptor method;
048: final String message;
049: long self;
050: long total;
051:
052: MethodCall(MethodDescriptor method, String message, long self,
053: long total) {
054: this .method = method;
055: this .message = message;
056: this .self = self;
057: this .total = total;
058: }
059: }
060:
061: // output device
062: PrintWriter out = new PrintWriter(System.out, true);
063:
064: // methods
065: HashMap methods = new HashMap();
066:
067: // method call stack
068: private final ArrayList calls = new ArrayList(16);
069:
070: public Timer() {
071: }
072:
073: public Timer(PrintWriter out) {
074: this .out = out;
075: }
076:
077: public final synchronized void push(String name) {
078: push(name, name);
079: }
080:
081: public final synchronized void push(String name, String message) {
082: // get time
083: final long now = System.currentTimeMillis();
084:
085: // get a method descriptor
086: MethodDescriptor current = (MethodDescriptor) methods.get(name);
087: if (current == null) {
088: current = new MethodDescriptor(name);
089: methods.put(name, current);
090: }
091:
092: // update method descriptor
093: current.calls++;
094: current.instantiations++;
095:
096: // update method call stack
097: calls.add(new MethodCall(current, message, now, now));
098: }
099:
100: public final synchronized void pop() {
101: // get time
102: final long now = System.currentTimeMillis();
103:
104: // update method call stack
105: final MethodCall call = (MethodCall) calls
106: .remove(calls.size() - 1);
107:
108: // get current call's time
109: final long currentSelf = now - call.self;
110: final long currentTotal = now - call.total;
111:
112: // update previous call's self time
113: if (calls.size() > 0) {
114: final MethodCall previous = (MethodCall) calls.get(calls
115: .size() - 1);
116: previous.self += currentTotal;
117: }
118:
119: // update method descriptor
120: final MethodDescriptor current = call.method;
121: current.self += currentSelf;
122: if (--current.instantiations == 0) {
123: current.total += currentTotal;
124: }
125:
126: if (false) {
127: out.println("Timer (n,g): " + call.message + " : ("
128: + currentSelf + ", " + currentTotal + ")");
129: }
130: }
131:
132: static private final String pad(String s, int i) {
133: StringBuffer b = new StringBuffer();
134: for (i -= s.length(); i > 0; i--)
135: b.append((char) ' ');
136: b.append(s);
137: return b.toString();
138: }
139:
140: public final synchronized void print() {
141: out.println("Timer : printing accumulated times ...");
142: final Object[] _calls = methods.values().toArray();
143:
144: Arrays.sort(_calls, new Comparator() {
145: public int compare(Object o1, Object o2) {
146: return (int) (((MethodDescriptor) o2).total - ((MethodDescriptor) o1).total);
147: }
148:
149: public boolean equals(Object obj) {
150: return (compare(this , obj) == 0);
151: }
152: });
153:
154: out.println("Timer : total s self s #calls name");
155: DecimalFormat nf = new DecimalFormat();
156: nf.setMaximumFractionDigits(2);
157: nf.setMinimumFractionDigits(2);
158: //nf.applyPattern("#,##0.00");
159: //out.println("Timer : pattern = " + nf.toPattern());
160: for (int i = 0; i < _calls.length; i++) {
161: final MethodDescriptor current = (MethodDescriptor) _calls[i];
162:
163: out.println("Timer : "
164: + pad(nf.format(current.total / 1000.0), 8) + " "
165: + pad(nf.format(current.self / 1000.0), 8) + " "
166: + pad(String.valueOf(current.calls), 6) + " "
167: + current.name);
168: }
169: }
170: }
|