001: /*
002: Copyright (c) 2005 - 2006, MentorGen, LLC
003: All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions are met:
007:
008: + Redistributions of source code must retain the above copyright notice,
009: this list of conditions and the following disclaimer.
010: + Redistributions in binary form must reproduce the above copyright notice,
011: this list of conditions and the following disclaimer in the documentation
012: and/or other materials provided with the distribution.
013: + Neither the name of MentorGen LLC nor the names of its contributors may be
014: used to endorse or promote products derived from this software without
015: specific prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
020: ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
021: LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
022: CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
023: SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
024: INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
025: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
026: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
027: POSSIBILITY OF SUCH DAMAGE.
028: */
029: package com.mentorgen.tools.profile.runtime;
030:
031: import java.util.ArrayList;
032: import java.util.HashMap;
033: import java.util.Map;
034:
035: import com.mentorgen.tools.profile.Controller;
036:
037: /**
038: * Models a (call) stack frame.
039: *
040: * @author Andrew Wilcox
041: *
042: */
043: public final class Frame {
044:
045: // identification
046: //
047: private Method _method;
048: private Frame _parent;
049: private long _netTime = 0;
050: private long _threadId;
051:
052: private Map<Method, Frame> _children = new HashMap<Method, Frame>();
053: private ArrayList<Frame> _childList = new ArrayList<Frame>();
054:
055: // metrics
056: //
057: public Metrics _metrics = new Metrics();
058: private long _lastStartTime = 0;
059: private long _lastWaitStartTime = 0;
060: private long _waitTime = 0;
061:
062: private Frame() {
063: }
064:
065: Frame(Frame parent, Method method, long threadId) {
066: assert method != null;
067: _parent = parent;
068: _method = method;
069: _threadId = threadId;
070:
071: if (parent != null) {
072: parent.addChild(method, this );
073: }
074: }
075:
076: //
077: // from object
078: //
079:
080: // for debugging
081: public String toString() {
082: StringBuffer b = new StringBuffer();
083: toStringBuffer(b, 0);
084: return b.toString();
085: }
086:
087: //
088: // public query methods
089: //
090:
091: public long getThreadId() {
092: return _threadId;
093: }
094:
095: public String getName() {
096: return _method.toString();
097: }
098:
099: public String getInvertedName() {
100: return _method.toInvertedString();
101: }
102:
103: public String getClassName() {
104: return _method.getClassName();
105: }
106:
107: public String getMethodName() {
108: return _method.getMethodName();
109: }
110:
111: public Iterable<Frame> childIterator() {
112: return _childList;
113: }
114:
115: public boolean hasChildren() {
116: return _childList.size() > 0;
117: }
118:
119: public Frame getParent() {
120: return _parent;
121: }
122:
123: public long netTime() {
124: return _netTime;
125: }
126:
127: //
128: // public "action" methods
129: //
130:
131: void computeNetTime() {
132: long childTime = 0;
133:
134: for (Frame child : _childList) {
135: childTime += child._metrics.getTotalTime();
136: }
137:
138: _netTime = _metrics.getTotalTime() - childTime - _waitTime;
139:
140: if (_netTime < 0) {
141: _netTime = 0;
142: }
143: }
144:
145: //
146: // package methods used by the runtime profiler
147: //
148:
149: void setBeginTime(long time) {
150: _lastStartTime = time;
151: }
152:
153: void setEndTime(long endTime) {
154: if (_lastStartTime == 0) {
155: _metrics.inc(0);
156: } else if (0 < (endTime - _lastStartTime)) {
157: _metrics.inc(endTime - _lastStartTime);
158: } else {
159: _metrics.inc(0);
160: }
161: _lastStartTime = 0;
162: }
163:
164: void beginWait(long time) {
165: _lastWaitStartTime = time;
166: }
167:
168: void endWait(long time) {
169: if (0 < (time - _lastWaitStartTime)) {
170: _waitTime += (time - _lastWaitStartTime);
171: }
172: _lastWaitStartTime = 0;
173: }
174:
175: Frame getChild(Method m) {
176: return _children.get(m);
177: }
178:
179: void overhead(long overhead) {
180: _metrics.adjust(overhead);
181: }
182:
183: void close() {
184: if (_lastStartTime > 0) {
185: this .setEndTime(System.nanoTime());
186:
187: if (Controller._debug) {
188: System.err.print("Fixup: ");
189: System.err.println(_method);
190: }
191: }
192:
193: // make sure that all of the child frames are closed
194: //
195: for (Frame child : _childList) {
196: child.close();
197: }
198: }
199:
200: //
201: // private
202: //
203:
204: private void addChild(Method m, Frame f) {
205: _children.put(m, f);
206: _childList.add(f);
207: }
208:
209: // very similar to a section of FrameDump
210: private void toStringBuffer(StringBuffer b, int depth) {
211: if (depth > 5) {
212: return;
213: }
214:
215: b.append(" ");
216:
217: for (int i = 0; i < depth; i++) {
218: b.append("| ");
219: }
220:
221: b.append("+--");
222: b.append(this .getInvertedName());
223: b.append(System.getProperty("line.separator"));
224:
225: if (Controller._threadDepth != Controller.UNLIMITED
226: && depth == Controller._threadDepth - 1) {
227: return;
228: }
229:
230: for (Frame child : _childList) {
231:
232: if (Controller._compactThreadDepth
233: && child._metrics.getTotalTime() < Controller._compactThreadThreshold * 1000000) {
234: continue;
235: }
236:
237: child.toStringBuffer(b, depth + 1);
238: }
239: }
240:
241: }
|