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