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.memory;
042:
043: import org.netbeans.lib.profiler.ProfilerClient;
044: import org.netbeans.lib.profiler.client.ClientUtils;
045:
046: /**
047: * Presentation-Time Object Liveness Profiling Calling Context Tree (CCT) Node.
048: *
049: * @author Misha Dmitriev
050: */
051: public class PresoObjLivenessCCTNode extends PresoObjAllocCCTNode {
052: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
053:
054: static int currentEpoch;
055: public static final int SORT_BY_LIVE_OBJ_SIZE = 1;
056: public static final int SORT_BY_LIVE_OBJ_NUMBER = 2;
057: public static final int SORT_BY_ALLOC_OBJ = 3;
058: public static final int SORT_BY_AVG_AGE = 4;
059: public static final int SORT_BY_SURV_GEN = 5;
060: public static final int SORT_BY_NAME = 6;
061: public static final int SORT_BY_TOTAL_ALLOC_OBJ = 7;
062: private static boolean dontShowZeroLiveObjNodes;
063:
064: //~ Instance fields ----------------------------------------------------------------------------------------------------------
065:
066: public float avgObjectAge;
067: public int nLiveObjects;
068: public int survGen;
069:
070: //~ Constructors -------------------------------------------------------------------------------------------------------------
071:
072: protected PresoObjLivenessCCTNode(RuntimeMemoryCCTNode rtNode) {
073: super (rtNode);
074: }
075:
076: //~ Methods ------------------------------------------------------------------------------------------------------------------
077:
078: public static PresoObjAllocCCTNode createPresentationCCTFromSnapshot(
079: LivenessMemoryResultsSnapshot snapshot,
080: RuntimeMemoryCCTNode rootRuntimeNode, String classTypeName,
081: int curEpoch, boolean dontShowZeroLiveObjAllocPaths) {
082: currentEpoch = curEpoch;
083: dontShowZeroLiveObjNodes = dontShowZeroLiveObjAllocPaths;
084:
085: SurvGenSet survGens = new SurvGenSet();
086:
087: PresoObjAllocCCTNode rootNode = generateMirrorNode(
088: rootRuntimeNode, survGens);
089:
090: if (rootNode != null) { // null means there are no live objects for any allocation path
091: assignNamesToNodesFromSnapshot(snapshot, rootNode,
092: classTypeName);
093: }
094:
095: return rootNode;
096: }
097:
098: public static PresoObjAllocCCTNode createPresentationCCTFromVM(
099: ProfilerClient profilerClient,
100: RuntimeMemoryCCTNode rootRuntimeNode, String classTypeName,
101: int curEpoch, boolean dontShowZeroLiveObjAllocPaths)
102: throws ClientUtils.TargetAppOrVMTerminated {
103: currentEpoch = curEpoch;
104: dontShowZeroLiveObjNodes = dontShowZeroLiveObjAllocPaths;
105:
106: SurvGenSet survGens = new SurvGenSet();
107:
108: PresoObjAllocCCTNode rootNode = generateMirrorNode(
109: rootRuntimeNode, survGens);
110:
111: if (rootNode != null) { // null means there are no live objects for any allocation path
112: assignNamesToNodesFromVM(profilerClient, rootNode,
113: classTypeName);
114: }
115:
116: return rootNode;
117: }
118:
119: public void sortChildren(int sortBy, boolean sortOrder) {
120: int nChildren = getNChildren();
121:
122: if (nChildren == 0) {
123: return;
124: }
125:
126: for (int i = 0; i < nChildren; i++) {
127: children[i].sortChildren(sortBy, sortOrder);
128: }
129:
130: if (nChildren > 1) {
131: switch (sortBy) {
132: case SORT_BY_LIVE_OBJ_SIZE:
133: sortChildrenByLiveObjSize(sortOrder);
134:
135: break;
136: case SORT_BY_LIVE_OBJ_NUMBER:
137: sortChildrenByLiveObjNumber(sortOrder);
138:
139: break;
140: case SORT_BY_ALLOC_OBJ:
141: sortChildrenByAllocObjNumber(sortOrder);
142:
143: break;
144: case SORT_BY_AVG_AGE:
145: sortChildrenByAvgAge(sortOrder);
146:
147: break;
148: case SORT_BY_SURV_GEN:
149: sortChildrenBySurvGen(sortOrder);
150:
151: break;
152: case SORT_BY_NAME:
153: sortChildrenByName(sortOrder);
154:
155: break;
156: }
157: }
158: }
159:
160: protected static PresoObjAllocCCTNode generateMirrorNode(
161: RuntimeMemoryCCTNode rtNode, SurvGenSet survGens) {
162: PresoObjLivenessCCTNode this Node = null;
163:
164: if (rtNode instanceof RuntimeObjLivenessTermCCTNode) { // A "terminal" node may occur even in the middle of the call chain
165:
166: RuntimeObjLivenessTermCCTNode rtTermNode = (RuntimeObjLivenessTermCCTNode) rtNode;
167: int nLiveObjects = rtTermNode.calculateTotalNLiveObjects();
168:
169: if (dontShowZeroLiveObjNodes && (nLiveObjects == 0)
170: && (rtNode.children == null)) {
171: return null;
172: }
173:
174: this Node = new PresoObjLivenessCCTNode(rtNode);
175: this Node.nLiveObjects = nLiveObjects;
176: //thisNode.survGen = RuntimeObjLivenessTermCCTNode.calculateTotalNumberOfSurvGensForAllPaths(rtTermNode);
177: RuntimeObjLivenessTermCCTNode
178: .calculateTotalNumberOfSurvGens(rtTermNode,
179: survGens);
180: this Node.survGen = survGens.getTotalNoOfAges();
181: this Node.avgObjectAge = RuntimeObjLivenessTermCCTNode
182: .calculateAvgObjectAgeForAllPaths(rtTermNode,
183: currentEpoch);
184:
185: if (rtNode.children != null) {
186: int len = (rtNode.children instanceof RuntimeMemoryCCTNode) ? 1
187: : ((RuntimeMemoryCCTNode[]) rtNode.children).length;
188: this Node.children = new PresoObjAllocCCTNode[len];
189: }
190: }
191:
192: Object nodeChildren = rtNode.children;
193:
194: if (nodeChildren != null) {
195: RuntimeMemoryCCTNode[] ar;
196:
197: if (nodeChildren instanceof RuntimeMemoryCCTNode) {
198: ar = new RuntimeMemoryCCTNode[1];
199: ar[0] = (RuntimeMemoryCCTNode) nodeChildren;
200: } else {
201: ar = (RuntimeMemoryCCTNode[]) nodeChildren;
202: }
203:
204: int nChildren = ar.length;
205:
206: if (nChildren > 0) {
207: double avgAge = 0;
208: int childIdx = 0;
209:
210: for (int i = 0; i < nChildren; i++) {
211: SurvGenSet subNodeSurvGens = (nChildren == 1) ? survGens
212: : new SurvGenSet();
213: PresoObjLivenessCCTNode child = (PresoObjLivenessCCTNode) generateMirrorNode(
214: ar[i], subNodeSurvGens);
215:
216: if (child != null) {
217: if (this Node == null) {
218: this Node = new PresoObjLivenessCCTNode(
219: rtNode);
220: this Node.children = new PresoObjAllocCCTNode[nChildren];
221: }
222: } else {
223: continue;
224: }
225:
226: this Node.children[childIdx++] = child;
227: child.parent = this Node;
228: this Node.nCalls += child.nCalls;
229: this Node.totalObjSize += child.totalObjSize;
230: this Node.nLiveObjects += child.nLiveObjects;
231: avgAge += (child.avgObjectAge * child.nLiveObjects);
232:
233: if (nChildren > 1) {
234: survGens.mergeWith(subNodeSurvGens);
235: }
236: }
237:
238: if (dontShowZeroLiveObjNodes
239: && ((this Node == null) || (this Node.nLiveObjects == 0))) {
240: return null;
241: }
242:
243: if (childIdx < nChildren) {
244: PresoObjAllocCCTNode[] newChildren = new PresoObjAllocCCTNode[childIdx];
245: System.arraycopy(this Node.children, 0, newChildren,
246: 0, childIdx);
247: this Node.children = newChildren;
248: }
249:
250: this Node.avgObjectAge = (this Node.nLiveObjects > 0) ? (float) (avgAge / this Node.nLiveObjects)
251: : 0;
252: this Node.survGen = survGens.getTotalNoOfAges();
253: }
254: }
255:
256: return this Node;
257: }
258:
259: protected void sortChildrenByAvgAge(boolean sortOrder) {
260: int len = children.length;
261: float[] values = new float[len];
262:
263: for (int i = 0; i < len; i++) {
264: values[i] = ((PresoObjLivenessCCTNode) children[i]).avgObjectAge;
265: }
266:
267: sortFloats(values, sortOrder);
268: }
269:
270: protected void sortChildrenByLiveObjNumber(boolean sortOrder) {
271: int len = children.length;
272: int[] values = new int[len];
273:
274: for (int i = 0; i < len; i++) {
275: values[i] = ((PresoObjLivenessCCTNode) children[i]).nLiveObjects;
276: }
277:
278: sortInts(values, sortOrder);
279: }
280:
281: protected void sortChildrenByLiveObjSize(boolean sortOrder) {
282: sortChildrenByAllocObjSize(sortOrder);
283: }
284:
285: protected void sortChildrenBySurvGen(boolean sortOrder) {
286: int len = children.length;
287: int[] values = new int[len];
288:
289: for (int i = 0; i < len; i++) {
290: values[i] = ((PresoObjLivenessCCTNode) children[i]).survGen;
291: }
292:
293: sortInts(values, sortOrder);
294: }
295: }
|