• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 
29 /**
30  * Creates a Profile View builder object.
31  *
32  * @param {number} samplingRate Number of ms between profiler ticks.
33  * @constructor
34  */
35 function ViewBuilder(samplingRate) {
36   this.samplingRate = samplingRate;
37 };
38 
39 
40 /**
41  * Builds a profile view for the specified call tree.
42  *
43  * @param {CallTree} callTree A call tree.
44  * @param {boolean} opt_bottomUpViewWeights Whether remapping
45  *     of self weights for a bottom up view is needed.
46  */
47 ViewBuilder.prototype.buildView = function(
48     callTree, opt_bottomUpViewWeights) {
49   var head;
50   var samplingRate = this.samplingRate;
51   var createViewNode = this.createViewNode;
52   callTree.traverse(function(node, viewParent) {
53     var totalWeight = node.totalWeight * samplingRate;
54     var selfWeight = node.selfWeight * samplingRate;
55     if (opt_bottomUpViewWeights === true) {
56       if (viewParent === head) {
57         selfWeight = totalWeight;
58       } else {
59         selfWeight = 0;
60       }
61     }
62     var viewNode = createViewNode(node.label, totalWeight, selfWeight, head);
63     if (viewParent) {
64       viewParent.addChild(viewNode);
65     } else {
66       head = viewNode;
67     }
68     return viewNode;
69   });
70   var view = this.createView(head);
71   return view;
72 };
73 
74 
75 /**
76  * Factory method for a profile view.
77  *
78  * @param {ProfileView.Node} head View head node.
79  * @return {ProfileView} Profile view.
80  */
81 ViewBuilder.prototype.createView = function(head) {
82   return new ProfileView(head);
83 };
84 
85 
86 /**
87  * Factory method for a profile view node.
88  *
89  * @param {string} internalFuncName A fully qualified function name.
90  * @param {number} totalTime Amount of time that application spent in the
91  *     corresponding function and its descendants (not that depending on
92  *     profile they can be either callees or callers.)
93  * @param {number} selfTime Amount of time that application spent in the
94  *     corresponding function only.
95  * @param {ProfileView.Node} head Profile view head.
96  * @return {ProfileView.Node} Profile view node.
97  */
98 ViewBuilder.prototype.createViewNode = function(
99     funcName, totalTime, selfTime, head) {
100   return new ProfileView.Node(
101       funcName, totalTime, selfTime, head);
102 };
103 
104 
105 /**
106  * Creates a Profile View object. It allows to perform sorting
107  * and filtering actions on the profile.
108  *
109  * @param {ProfileView.Node} head Head (root) node.
110  * @constructor
111  */
112 function ProfileView(head) {
113   this.head = head;
114 };
115 
116 
117 /**
118  * Sorts the profile view using the specified sort function.
119  *
120  * @param {function(ProfileView.Node,
121  *     ProfileView.Node):number} sortFunc A sorting
122  *     functions. Must comply with Array.sort sorting function requirements.
123  */
124 ProfileView.prototype.sort = function(sortFunc) {
125   this.traverse(function (node) {
126     node.sortChildren(sortFunc);
127   });
128 };
129 
130 
131 /**
132  * Traverses profile view nodes in preorder.
133  *
134  * @param {function(ProfileView.Node)} f Visitor function.
135  */
136 ProfileView.prototype.traverse = function(f) {
137   var nodesToTraverse = new ConsArray();
138   nodesToTraverse.concat([this.head]);
139   while (!nodesToTraverse.atEnd()) {
140     var node = nodesToTraverse.next();
141     f(node);
142     nodesToTraverse.concat(node.children);
143   }
144 };
145 
146 
147 /**
148  * Constructs a Profile View node object. Each node object corresponds to
149  * a function call.
150  *
151  * @param {string} internalFuncName A fully qualified function name.
152  * @param {number} totalTime Amount of time that application spent in the
153  *     corresponding function and its descendants (not that depending on
154  *     profile they can be either callees or callers.)
155  * @param {number} selfTime Amount of time that application spent in the
156  *     corresponding function only.
157  * @param {ProfileView.Node} head Profile view head.
158  * @constructor
159  */
160 ProfileView.Node = function(
161     internalFuncName, totalTime, selfTime, head) {
162   this.internalFuncName = internalFuncName;
163   this.totalTime = totalTime;
164   this.selfTime = selfTime;
165   this.head = head;
166   this.parent = null;
167   this.children = [];
168 };
169 
170 
171 /**
172  * Returns a share of the function's total time in its parent's total time.
173  */
174 ProfileView.Node.prototype.__defineGetter__(
175     'parentTotalPercent',
176     function() { return this.totalTime /
177       (this.parent ? this.parent.totalTime : this.totalTime) * 100.0; });
178 
179 
180 /**
181  * Adds a child to the node.
182  *
183  * @param {ProfileView.Node} node Child node.
184  */
185 ProfileView.Node.prototype.addChild = function(node) {
186   node.parent = this;
187   this.children.push(node);
188 };
189 
190 
191 /**
192  * Sorts all the node's children recursively.
193  *
194  * @param {function(ProfileView.Node,
195  *     ProfileView.Node):number} sortFunc A sorting
196  *     functions. Must comply with Array.sort sorting function requirements.
197  */
198 ProfileView.Node.prototype.sortChildren = function(
199     sortFunc) {
200   this.children.sort(sortFunc);
201 };
202