001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.results.cpu.cct;
042:
043: import org.netbeans.lib.profiler.ProfilerClient;
044: import org.netbeans.lib.profiler.global.InstrumentationFilter;
045: import org.netbeans.lib.profiler.global.ProfilingSessionStatus;
046: import org.netbeans.lib.profiler.results.cpu.FlatProfileContainer;
047: import org.netbeans.lib.profiler.results.cpu.FlatProfileContainerFree;
048: import org.netbeans.lib.profiler.results.cpu.TimingAdjusterOld;
049: import org.netbeans.lib.profiler.results.cpu.cct.nodes.MethodCPUCCTNode;
050: import org.netbeans.lib.profiler.results.cpu.cct.nodes.ThreadCPUCCTNode;
051: import org.netbeans.lib.profiler.results.cpu.cct.nodes.TimedCPUCCTNode;
052: import java.util.Stack;
053: import java.util.logging.Level;
054: import java.util.logging.Logger;
055:
056: /**
057: *
058: * @author Jaroslav Bachorik
059: */
060: public class CCTFlattener extends CPUCCTVisitorAdapter {
061: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
062:
063: private static final Logger LOGGER = Logger
064: .getLogger(CCTFlattener.class.getName());
065:
066: //~ Instance fields ----------------------------------------------------------------------------------------------------------
067:
068: private final Object containerGuard = new Object();
069:
070: // @GuardedBy containerGuard
071: private FlatProfileContainer container;
072: private ProfilerClient client;
073: private Stack parentStack;
074: private int[] invDiff;
075: private int[] invPM;
076: private int[] nCalleeInvocations;
077: private long[] timePM0;
078: private long[] timePM1;
079: private int nMethods;
080:
081: //~ Constructors -------------------------------------------------------------------------------------------------------------
082:
083: public CCTFlattener(ProfilerClient client) {
084: this .client = client;
085: parentStack = new Stack();
086: }
087:
088: //~ Methods ------------------------------------------------------------------------------------------------------------------
089:
090: public FlatProfileContainer getFlatProfile() {
091: synchronized (containerGuard) {
092: return container;
093: }
094: }
095:
096: public void afterWalk() {
097: ProfilingSessionStatus status = client.getStatus();
098:
099: // Now convert the data into microseconds
100: long wholeGraphTime0 = 0;
101:
102: // Now convert the data into microseconds
103: long wholeGraphTime1 = 0;
104: long totalNInv = 0;
105:
106: for (int i = 0; i < nMethods; i++) {
107: double time = TimingAdjusterOld
108: .getDefault(status)
109: .adjustTime(timePM0[i], (invPM[i] + invDiff[i]),
110: (nCalleeInvocations[i] + invDiff[i]), false);
111:
112: if (time < 0) {
113: // in some cases the combination of cleansing the time by calibration and subtracting wait/sleep
114: // times can lead to <0 time
115: // see http://profiler.netbeans.org/issues/show_bug.cgi?id=64416
116: time = 0;
117: }
118:
119: timePM0[i] = (long) time;
120:
121: // don't include the Thread time into wholegraphtime
122: if (i > 0) {
123: wholeGraphTime0 += time;
124: }
125:
126: if (status.collectingTwoTimeStamps()) {
127: time = TimingAdjusterOld.getDefault(status).adjustTime(
128: timePM1[i], (invPM[i] + invDiff[i]),
129: (nCalleeInvocations[i] + invDiff[i]), true);
130: timePM1[i] = (long) time;
131:
132: // don't include the Thread time into wholegraphtime
133: if (i > 0) {
134: wholeGraphTime1 += time;
135: }
136: }
137:
138: totalNInv += invPM[i];
139: }
140:
141: synchronized (containerGuard) {
142: container = new FlatProfileContainerFree(status, timePM0,
143: timePM1, invPM, new char[0], wholeGraphTime0,
144: wholeGraphTime1, invPM.length);
145: }
146:
147: timePM0 = timePM1 = null;
148: invPM = invDiff = nCalleeInvocations = null;
149: parentStack.clear();
150: }
151:
152: public void beforeWalk() {
153: ProfilingSessionStatus status = client.getStatus();
154: nMethods = status.getNInstrMethods();
155: timePM0 = new long[nMethods];
156: timePM1 = new long[status.collectingTwoTimeStamps() ? nMethods
157: : 0];
158: invPM = new int[nMethods];
159: invDiff = new int[nMethods];
160: nCalleeInvocations = new int[nMethods];
161: parentStack.clear();
162:
163: synchronized (containerGuard) {
164: container = null;
165: }
166: }
167:
168: public void visit(MethodCPUCCTNode node) {
169: ProfilingSessionStatus status = client.getStatus();
170: InstrumentationFilter filter = client.getSettings()
171: .getInstrumentationFilter();
172:
173: MethodCPUCCTNode currentParent = parentStack.isEmpty() ? null
174: : (MethodCPUCCTNode) parentStack.peek();
175: boolean filteredOut = (node.getFilteredStatus() == TimedCPUCCTNode.FILTERED_YES); // filtered out by rootmethod/markermethod rules
176:
177: if (!filteredOut
178: && (node.getFilteredStatus() == TimedCPUCCTNode.FILTERED_MAYBE)) { // filter out all methods not complying to instrumentation filter & secure to remove
179:
180: String jvmClassName = status.getInstrMethodClasses()[node
181: .getMethodId()].replace('.', '/');
182:
183: if (!filter.passesFilter(jvmClassName)) {
184: filteredOut = true;
185: }
186: }
187:
188: if (!filteredOut && (client.getMarkFilter() != null)) {
189: filteredOut = !client.getMarkFilter().passesFilter(); // finally use the mark filter
190: }
191:
192: if (LOGGER.isLoggable(Level.FINEST)) {
193: LOGGER
194: .finest("Processing runtime node: " // NOI18N
195: + status.getInstrMethodClasses()[node
196: .getMethodId()]
197: + "."
198: + status.getInstrMethodNames()[node
199: .getMethodId()]
200: + "; filtered="
201: + filteredOut); // NOI18N
202:
203: String parentInfo = (currentParent != null) ? (status
204: .getInstrMethodClasses()[currentParent
205: .getMethodId()]
206: + "." + status.getInstrMethodNames()[currentParent
207: .getMethodId()]) : "none"; // NOI18N
208: LOGGER.finest("Currently used parent: " + parentInfo); // NOI18N
209: }
210:
211: if (filteredOut) {
212: if ((currentParent != null) && !currentParent.isRoot()) {
213: invDiff[currentParent.getMethodId()] += node
214: .getNCalls();
215:
216: timePM0[currentParent.getMethodId()] += node
217: .getNetTime0();
218:
219: if (status.collectingTwoTimeStamps()) {
220: timePM1[currentParent.getMethodId()] += node
221: .getNetTime1();
222: }
223: }
224: } else {
225: timePM0[node.getMethodId()] += node.getNetTime0();
226:
227: if (status.collectingTwoTimeStamps()) {
228: timePM1[node.getMethodId()] += node.getNetTime1();
229: }
230:
231: invPM[node.getMethodId()] += node.getNCalls();
232:
233: if ((currentParent != null) && !currentParent.isRoot()) {
234: nCalleeInvocations[currentParent.getMethodId()] += node
235: .getNCalls();
236: }
237:
238: currentParent = node;
239: }
240:
241: parentStack.push(currentParent);
242: }
243:
244: public void visitPost(MethodCPUCCTNode node) {
245: parentStack.pop();
246: }
247:
248: public void visitPost(ThreadCPUCCTNode node) {
249: parentStack.clear();
250: }
251: }
|