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;
042:
043: import org.netbeans.lib.profiler.utils.IntVector;
044: import java.util.Enumeration;
045: import java.util.Hashtable;
046:
047: /**
048: * An extension of CPUCCTContainer that has functionality to build a class- or package-level CCT out of the method-level CCT.
049: *
050: * @author Misha Dmitriev
051: */
052: public class CPUCCTClassContainer extends CPUCCTContainer {
053: //~ Instance fields ----------------------------------------------------------------------------------------------------------
054:
055: protected int view;
056:
057: //-- Temporary data used during construction
058: private CPUCCTContainer sourceContainer;
059: private MethodIdMap methodIdMap;
060: private long childTotalTime0;
061: private long childTotalTime1;
062:
063: //~ Constructors -------------------------------------------------------------------------------------------------------------
064:
065: public CPUCCTClassContainer(CPUCCTContainer sourceContainer,
066: MethodIdMap methodIdMap, int view) {
067: super (sourceContainer.cpuResSnapshot);
068: this .view = view;
069: this .sourceContainer = sourceContainer;
070: this .threadId = sourceContainer.threadId;
071: this .threadName = sourceContainer.threadName;
072: this .wholeGraphNetTime0 = sourceContainer.wholeGraphNetTime0;
073: this .wholeGraphNetTime1 = sourceContainer.wholeGraphNetTime1;
074: this .childOfsSize = CHILD_OFS_SIZE_3;
075:
076: collectingTwoTimeStamps = sourceContainer.collectingTwoTimeStamps;
077: nodeSize = sourceContainer.nodeSize;
078:
079: compactData = new byte[sourceContainer.compactData.length]; // Initially create a same-sized array - should be more than enough
080:
081: this .methodIdMap = methodIdMap;
082:
083: IntVector rootMethodVec = new IntVector();
084: rootMethodVec.add(0);
085:
086: int lastOfs = generateClassNodeFromMethodNodes(rootMethodVec, 0);
087:
088: // Create an array of appropriate size
089: byte[] oldData = compactData;
090: compactData = new byte[lastOfs];
091: System.arraycopy(oldData, 0, compactData, 0, lastOfs);
092: oldData = null;
093:
094: rootNode = new PrestimeCPUCCTNodeBacked(this , null, 0);
095:
096: if (rootNode.getMethodId() == 0) {
097: rootNode.setThreadNode();
098: }
099:
100: methodIdMap = null;
101: }
102:
103: //~ Methods ------------------------------------------------------------------------------------------------------------------
104:
105: public String[] getMethodClassNameAndSig(int methodId) {
106: return cpuResSnapshot.getMethodClassNameAndSig(methodId, view);
107: }
108:
109: /**
110: * For a given vector of source (method-level) nodes, where all nodes have the same class, generate
111: * a single class-level node. Do the same with all the source node's children.
112: * Returns the offset right after the last generated node, which is this node if it has no children,
113: * or the last recursive child of this node.
114: */
115: protected int generateClassNodeFromMethodNodes(
116: IntVector methodNodes, int dataOfs) {
117: int nMethodNodes = methodNodes.size();
118: int nCalls = 0;
119: long time0 = 0;
120: long time1 = 0;
121:
122: for (int i = 0; i < nMethodNodes; i++) {
123: int methodNodeOfs = methodNodes.get(i);
124: nCalls += sourceContainer
125: .getNCallsForNodeOfs(methodNodeOfs);
126: time0 += sourceContainer
127: .getSelfTime0ForNodeOfs(methodNodeOfs);
128:
129: if (collectingTwoTimeStamps) {
130: time1 += sourceContainer
131: .getSelfTime1ForNodeOfs(methodNodeOfs);
132: }
133: }
134:
135: int methodId = sourceContainer
136: .getMethodIdForNodeOfs(methodNodes.get(0));
137:
138: if (methodId != 0) {
139: methodId = methodIdMap
140: .getClassOrPackageIdForMethodId(methodId);
141: }
142:
143: setMethodIdForNodeOfs(dataOfs, methodId);
144: setNCallsForNodeOfs(dataOfs, nCalls);
145: setSelfTime0ForNodeOfs(dataOfs, time0);
146:
147: if (collectingTwoTimeStamps) {
148: setSelfTime1ForNodeOfs(dataOfs, time1);
149: }
150:
151: // Now add all the children of methodNodes that have the same class, to thisNode, and collect the rest of the
152: // children of methodNodes into sourceChildren vector.
153: IntVector sourceChildren = new IntVector();
154: Hashtable uniqChildrenCache = new Hashtable();
155:
156: for (int i = 0; i < nMethodNodes; i++) {
157: int methodNodeOfs = methodNodes.get(i);
158: int nChildren = sourceContainer
159: .getNChildrenForNodeOfs(methodNodeOfs);
160:
161: if (nChildren > 0) {
162: processChildren(dataOfs, methodNodeOfs, nChildren,
163: sourceChildren, uniqChildrenCache);
164: }
165: }
166:
167: int this NodeNChildren = uniqChildrenCache.size();
168: int nextNodeOfs = dataOfs + nodeSize
169: + (this NodeNChildren * childOfsSize);
170:
171: if (this NodeNChildren == 0) {
172: childTotalTime0 = getSelfTime0ForNodeOfs(dataOfs); // We are effectively returning these values
173:
174: if (collectingTwoTimeStamps) {
175: childTotalTime1 = getSelfTime1ForNodeOfs(dataOfs);
176: }
177:
178: setTotalTime0ForNodeOfs(dataOfs, childTotalTime0);
179:
180: if (collectingTwoTimeStamps) {
181: setTotalTime1ForNodeOfs(dataOfs, childTotalTime1);
182: }
183:
184: return nextNodeOfs;
185: } else {
186: time0 = getSelfTime0ForNodeOfs(dataOfs);
187:
188: if (collectingTwoTimeStamps) {
189: time1 = getSelfTime1ForNodeOfs(dataOfs);
190: }
191: }
192:
193: setNChildrenForNodeOfs(dataOfs, this NodeNChildren);
194:
195: IntVector sameTypeChildren = new IntVector();
196: int nAllChildren = sourceChildren.size();
197: int[] sourceChildrenClassIds = new int[nAllChildren];
198:
199: for (int i = 0; i < nAllChildren; i++) {
200: sourceChildrenClassIds[i] = methodIdMap
201: .getClassOrPackageIdForMethodId(sourceContainer
202: .getMethodIdForNodeOfs(sourceChildren
203: .get(i)));
204: }
205:
206: Enumeration e = uniqChildrenCache.elements();
207:
208: for (int i = 0; e.hasMoreElements(); i++) {
209: sameTypeChildren.clear();
210:
211: int sourceChildClassOrPackageId = ((Integer) e
212: .nextElement()).intValue();
213:
214: for (int j = 0; j < nAllChildren; j++) {
215: if (sourceChildrenClassIds[j] == sourceChildClassOrPackageId) {
216: sameTypeChildren.add(sourceChildren.get(j));
217: }
218: }
219:
220: setChildOfsForNodeOfs(dataOfs, i, nextNodeOfs);
221:
222: nextNodeOfs = generateClassNodeFromMethodNodes(
223: sameTypeChildren, nextNodeOfs);
224: time0 += childTotalTime0;
225:
226: if (collectingTwoTimeStamps) {
227: time1 += childTotalTime1;
228: }
229: }
230:
231: setTotalTime0ForNodeOfs(dataOfs, time0);
232:
233: if (collectingTwoTimeStamps) {
234: setTotalTime1ForNodeOfs(dataOfs, time1);
235: }
236:
237: childTotalTime0 = time0;
238:
239: if (collectingTwoTimeStamps) {
240: childTotalTime1 = time1;
241: }
242:
243: return nextNodeOfs;
244: }
245:
246: /**
247: * Given this target node, and the array of its source-level children, treat them as follows:
248: * 1. The info for a source child who has the same class as this node, is added to this node.
249: * Its own children are processed recursively by calling this same method.
250: * 2. The first source child whose class is different and was not observed before (not contained
251: * in uniqChildCache) is added to uniqChildCache, and to allSourceChildren.
252: * 3. All other source children are added to allSourceChildren, but not to uniqChildCache.
253: */
254: protected void processChildren(int dataOfs, int methodNodeOfs,
255: int nChildren, IntVector allSourceChildren,
256: Hashtable uniqChildCache) {
257: int this NodeClassOrPackageId = getMethodIdForNodeOfs(dataOfs);
258:
259: int nCalls = 0;
260: long time0 = 0;
261: long time1 = 0;
262:
263: for (int i = 0; i < nChildren; i++) {
264: int sourceChildOfs = sourceContainer.getChildOfsForNodeOfs(
265: methodNodeOfs, i);
266: int sourceChildClassOrPackageId = methodIdMap
267: .getClassOrPackageIdForMethodId(sourceContainer
268: .getMethodIdForNodeOfs(sourceChildOfs));
269:
270: if (sourceChildClassOrPackageId == this NodeClassOrPackageId) { // A child node has the same class as this node
271: nCalls += sourceContainer
272: .getNCallsForNodeOfs(sourceChildOfs);
273: time0 += sourceContainer
274: .getSelfTime0ForNodeOfs(sourceChildOfs);
275:
276: if (collectingTwoTimeStamps) {
277: time1 += sourceContainer
278: .getSelfTime1ForNodeOfs(sourceChildOfs);
279: }
280:
281: // sourceChild's children logically become this node's children now.
282: int nSourceChildChildren = sourceContainer
283: .getNChildrenForNodeOfs(sourceChildOfs);
284:
285: if (nSourceChildChildren > 0) {
286: this .processChildren(dataOfs, sourceChildOfs,
287: nSourceChildChildren, allSourceChildren,
288: uniqChildCache);
289: }
290: } else { // A child node belongs to a different class
291:
292: Integer key = new Integer(sourceChildClassOrPackageId);
293:
294: if (!uniqChildCache.containsKey(key)) {
295: uniqChildCache.put(key, key);
296: }
297:
298: allSourceChildren.add(sourceChildOfs);
299: }
300: }
301:
302: nCalls += getNCallsForNodeOfs(dataOfs);
303: time0 += getSelfTime0ForNodeOfs(dataOfs);
304:
305: if (collectingTwoTimeStamps) {
306: time1 += getSelfTime1ForNodeOfs(dataOfs);
307: }
308:
309: setNCallsForNodeOfs(dataOfs, nCalls);
310: setSelfTime0ForNodeOfs(dataOfs, time0);
311:
312: if (collectingTwoTimeStamps) {
313: setSelfTime1ForNodeOfs(dataOfs, time1);
314: }
315: }
316: }
|