001: /*
002: * Copyright (c) 1998-2005 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Sam
027: */
028:
029: package com.caucho.tools.profiler;
030:
031: import java.util.*;
032: import com.caucho.util.*;
033:
034: /**
035: * Represents a unique point at which profiling is performed. Obtained from a
036: * {@link ProfilerManager}. Equality between two instances of ProfilerPoint is
037: * based on the name only.
038: */
039: public class ProfilerPoint implements Comparable<ProfilerPoint> {
040: private static final Profiler NOOP_PROFILER;
041:
042: private final ProfilerManager _profilerManager;
043: private final String _name;
044:
045: private LruCache<String, ProfilerPoint> _children;
046:
047: private long _time;
048: private long _invocationCount;
049:
050: private long _minTime = Long.MAX_VALUE;
051: private long _maxTime = Long.MIN_VALUE;
052:
053: ProfilerPoint(ProfilerManager profilerManager, String name) {
054: assert profilerManager != null;
055: assert name != null;
056:
057: _profilerManager = profilerManager;
058: _name = name;
059: }
060:
061: protected ProfilerManager getProfilerManager() {
062: return _profilerManager;
063: }
064:
065: public String getName() {
066: return _name;
067: }
068:
069: public ProfilerPoint addProfilerPoint(String name) {
070: synchronized (this ) {
071: if (_children == null)
072: _children = new LruCache<String, ProfilerPoint>(1024);
073:
074: ProfilerPoint child = _children.get(name);
075:
076: if (child == null) {
077: child = create(name);
078: _children.put(name, child);
079: }
080:
081: return child;
082: }
083: }
084:
085: protected ProfilerPoint create(String name) {
086: return new ProfilerPoint(getProfilerManager(), name);
087: }
088:
089: public Profiler start() {
090: if (!_profilerManager.isEnabled())
091: return NOOP_PROFILER;
092:
093: ThreadProfiler profiler = ThreadProfiler.current();
094:
095: profiler.start(this );
096:
097: return profiler;
098: }
099:
100: protected Profiler start(ProfilerPoint parent) {
101: if (!getProfilerManager().isEnabled())
102: return NOOP_PROFILER;
103:
104: ThreadProfiler profiler = ThreadProfiler.current();
105:
106: profiler.start(parent, this );
107:
108: return profiler;
109: }
110:
111: /**
112: * Caller must synchronize on this ProfilerPoint while it uses the returned
113: * map.
114: */
115: List<ProfilerPoint> getChildren() {
116: if (_children == null)
117: return Collections.emptyList();
118: else {
119: ArrayList<ProfilerPoint> children = new ArrayList<ProfilerPoint>();
120:
121: Iterator<ProfilerPoint> iter = _children.values();
122: while (iter.hasNext())
123: children.add(iter.next());
124:
125: return children;
126: }
127: }
128:
129: /**
130: * Increment the invocation count and add time.
131: *
132: * @param totalTime
133: */
134: void update(long totalTime) {
135: synchronized (this ) {
136: _invocationCount++;
137:
138: if (_invocationCount > 0) {
139: _time += totalTime;
140: }
141:
142: if (totalTime < _minTime)
143: _minTime = totalTime;
144:
145: if (_maxTime < totalTime)
146: _maxTime = totalTime;
147: }
148: }
149:
150: /**
151: * Time for this node in nanoseconds, does not include the time for child
152: * nodes.
153: */
154: public long getTime() {
155: return _time;
156: }
157:
158: /**
159: * Minimum time for this node in nanoseconds, does not include
160: * the time for child nodes.
161: */
162: public long getMinTime() {
163: return _minTime;
164: }
165:
166: /**
167: * Minimum time for this node in nanoseconds, does not include
168: * the time for child nodes.
169: */
170: public long getMaxTime() {
171: return _maxTime;
172: }
173:
174: void incrementInvocationCount() {
175: synchronized (this ) {
176: _invocationCount++;
177: }
178: }
179:
180: public long getInvocationCount() {
181: return _invocationCount;
182: }
183:
184: /**
185: * Drop all of the children
186: */
187: void reset() {
188: _children = null;
189:
190: _time = 0;
191: _invocationCount = 0;
192:
193: _minTime = Long.MAX_VALUE;
194: _maxTime = Long.MIN_VALUE;
195: }
196:
197: public boolean equals(Object o) {
198: if (o == this )
199: return true;
200:
201: if (!(o instanceof ProfilerPoint))
202: return false;
203:
204: ProfilerPoint point = (ProfilerPoint) o;
205:
206: return getName().equals(point.getName());
207: }
208:
209: public int compareTo(ProfilerPoint point) {
210: return getName().compareTo(point.getName());
211: }
212:
213: public int hashCode() {
214: return getName().hashCode();
215: }
216:
217: public String toString() {
218: return "ProfilerPoint[" + getName() + "]";
219: }
220:
221: static {
222: NOOP_PROFILER = new Profiler() {
223: public void finish() {
224: }
225:
226: public String toString() {
227: return "NoopProfiler[]";
228: }
229: };
230: }
231: }
|