Home | History | Annotate | Download | only in tools
      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 application's total time.
    173  */
    174 ProfileView.Node.prototype.__defineGetter__(
    175     'totalPercent',
    176     function() { return this.totalTime /
    177       (this.head ? this.head.totalTime : this.totalTime) * 100.0; });
    178 
    179 
    180 /**
    181  * Returns a share of the function's self time in application's total time.
    182  */
    183 ProfileView.Node.prototype.__defineGetter__(
    184     'selfPercent',
    185     function() { return this.selfTime /
    186       (this.head ? this.head.totalTime : this.totalTime) * 100.0; });
    187 
    188 
    189 /**
    190  * Returns a share of the function's total time in its parent's total time.
    191  */
    192 ProfileView.Node.prototype.__defineGetter__(
    193     'parentTotalPercent',
    194     function() { return this.totalTime /
    195       (this.parent ? this.parent.totalTime : this.totalTime) * 100.0; });
    196 
    197 
    198 /**
    199  * Adds a child to the node.
    200  *
    201  * @param {ProfileView.Node} node Child node.
    202  */
    203 ProfileView.Node.prototype.addChild = function(node) {
    204   node.parent = this;
    205   this.children.push(node);
    206 };
    207 
    208 
    209 /**
    210  * Sorts all the node's children recursively.
    211  *
    212  * @param {function(ProfileView.Node,
    213  *     ProfileView.Node):number} sortFunc A sorting
    214  *     functions. Must comply with Array.sort sorting function requirements.
    215  */
    216 ProfileView.Node.prototype.sortChildren = function(
    217     sortFunc) {
    218   this.children.sort(sortFunc);
    219 };
    220