001: /*/////////////////////////////////////////////////////////////////////
002:
003: Copyright (C) 2006 TiVo Inc. 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 TiVo Inc 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: /////////////////////////////////////////////////////////////////////*/
030:
031: package com.tivo.jipviewer;
032:
033: import java.awt.BorderLayout;
034: import java.awt.Container;
035: import java.util.Enumeration;
036:
037: import javax.swing.JTree;
038: import javax.swing.tree.DefaultMutableTreeNode;
039:
040: class ByPackageViewer extends Container {
041:
042: ByPackageViewer(JipRun run) {
043: setLayout(new BorderLayout());
044: add(makeTree(run), BorderLayout.CENTER);
045: }
046:
047: //
048: // tree view of the world...
049: //
050:
051: static class TreeNode extends DefaultMutableTreeNode {
052: // name of this part of the package space
053: String mName;
054:
055: // starts as 1. is set during computeTotals. is always non-0!
056: private double mTimeDenominator = 1.0;
057:
058: // stats for methods in this package
059: private long mSelfNetTime;
060: private long mSelfCount;
061:
062: // stats for methods in this package and its "sub"packages.
063: private long mTotalNetTime;
064: private long mTotalCount;
065:
066: TreeNode(String name) {
067: mName = name;
068: }
069:
070: String getName() {
071: return mName;
072: }
073:
074: void addFrame(JipFrame frame) {
075: mSelfNetTime += frame.getNetTime();
076: mSelfCount += frame.getCount();
077: }
078:
079: private void computeTotals() {
080: computeTotalsHelper();
081:
082: // *after* we've computed mTotalNetTime on the root,
083: // set mTimeDenominator (if non-zero).
084: if (mTotalNetTime > 0) {
085: for (Enumeration nodes = breadthFirstEnumeration(); nodes
086: .hasMoreElements();
087: /**/) {
088: TreeNode kid = (TreeNode) nodes.nextElement();
089: kid.mTimeDenominator = mTotalNetTime;
090: }
091: }
092: }
093:
094: private void computeTotalsHelper() {
095: for (Enumeration kids = children(); kids.hasMoreElements(); /**/) {
096: TreeNode kid = (TreeNode) kids.nextElement();
097: kid.computeTotalsHelper();
098: mTotalCount += kid.mTotalCount;
099: mTotalNetTime += kid.mTotalNetTime;
100: }
101:
102: mTotalCount += mSelfCount;
103: mTotalNetTime += mSelfNetTime;
104: }
105:
106: public String toString() {
107: String str = (mName + " "
108: + toPercent(mTotalNetTime / mTimeDenominator) + " "
109: + toMsec(mTotalNetTime) + "ms");
110:
111: if (!isLeaf() && mSelfNetTime != 0) {
112: str = (str + " (self: "
113: + toPercent(mSelfNetTime / mTimeDenominator)
114: + " " + +toMsec(mSelfNetTime) + "ms)");
115: }
116: return str;
117: }
118:
119: private static long toMsec(long time) {
120: final double timeToMsec = 1000.0 * 1000.0;
121: return Math.round(time / timeToMsec);
122: }
123:
124: String toPercent(double fraction) {
125: double p = Math.floor(100 * 100 * fraction) / 100;
126: return Double.toString(p) + "%";
127: }
128: }
129:
130: static JTree makeTree(JipRun run) {
131: TreeNode root = makePackageTree(run);
132:
133: return new JTree(root);
134: }
135:
136: private static TreeNode makePackageTree(JipRun run) {
137: TreeNode root = new TreeNode("root");
138:
139: for (Long threadId : run.threads()) {
140: for (JipFrame f : run.interactions(threadId)) {
141: visitFrameForPackaging(root, f);
142: }
143: }
144:
145: root.computeTotals();
146: return root;
147: }
148:
149: private static void visitFrameForPackaging(TreeNode root,
150: JipFrame frame) {
151: String pkg = frame.getMethod().getPackageName();
152:
153: // add info for this frame
154: TreeNode node = findOrCreateNode(root, pkg);
155: node.addFrame(frame);
156:
157: // add info for this frame's children
158: for (JipFrame childFrame : frame.getChildren()) {
159: visitFrameForPackaging(root, childFrame);
160: }
161: };
162:
163: private static TreeNode findOrCreateNode(TreeNode node,
164: String pkgName) {
165: if (pkgName.equals("")) {
166: // we found the node.
167: return node;
168: }
169:
170: // split out the next part of the name.
171: String name;
172: String rest;
173: int iDot = pkgName.indexOf('.');
174: if (iDot == -1) {
175: name = pkgName;
176: rest = "";
177: } else {
178: name = pkgName.substring(0, iDot);
179: rest = pkgName.substring(iDot + 1);
180: }
181:
182: // does the name exist already as a kid of the node we were given?
183: for (Enumeration kids = node.children(); kids.hasMoreElements(); /**/) {
184: TreeNode kid = (TreeNode) kids.nextElement();
185: if (kid.getName().equals(name)) {
186: return findOrCreateNode(kid, rest);
187: }
188: }
189:
190: // didn't find it, so make a new node, and look for the rest...
191: TreeNode newKid = new TreeNode(name);
192: node.add(newKid);
193: return findOrCreateNode(newKid, rest);
194: }
195: }
|