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 // Initlialize namespaces
     30 var devtools = devtools || {};
     31 devtools.profiler = devtools.profiler || {};
     32 
     33 
     34 /**
     35  * Creates a Profile View builder object.
     36  *
     37  * @param {number} samplingRate Number of ms between profiler ticks.
     38  * @constructor
     39  */
     40 devtools.profiler.ViewBuilder = function(samplingRate) {
     41   this.samplingRate = samplingRate;
     42 };
     43 
     44 
     45 /**
     46  * Builds a profile view for the specified call tree.
     47  *
     48  * @param {devtools.profiler.CallTree} callTree A call tree.
     49  * @param {boolean} opt_bottomUpViewWeights Whether remapping
     50  *     of self weights for a bottom up view is needed.
     51  */
     52 devtools.profiler.ViewBuilder.prototype.buildView = function(
     53     callTree, opt_bottomUpViewWeights) {
     54   var head;
     55   var samplingRate = this.samplingRate;
     56   var createViewNode = this.createViewNode;
     57   callTree.traverse(function(node, viewParent) {
     58     var totalWeight = node.totalWeight * samplingRate;
     59     var selfWeight = node.selfWeight * samplingRate;
     60     if (opt_bottomUpViewWeights === true) {
     61       if (viewParent === head) {
     62         selfWeight = totalWeight;
     63       } else {
     64         selfWeight = 0;
     65       }
     66     }
     67     var viewNode = createViewNode(node.label, totalWeight, selfWeight, head);
     68     if (viewParent) {
     69       viewParent.addChild(viewNode);
     70     } else {
     71       head = viewNode;
     72     }
     73     return viewNode;
     74   });
     75   var view = this.createView(head);
     76   return view;
     77 };
     78 
     79 
     80 /**
     81  * Factory method for a profile view.
     82  *
     83  * @param {devtools.profiler.ProfileView.Node} head View head node.
     84  * @return {devtools.profiler.ProfileView} Profile view.
     85  */
     86 devtools.profiler.ViewBuilder.prototype.createView = function(head) {
     87   return new devtools.profiler.ProfileView(head);
     88 };
     89 
     90 
     91 /**
     92  * Factory method for a profile view node.
     93  *
     94  * @param {string} internalFuncName A fully qualified function name.
     95  * @param {number} totalTime Amount of time that application spent in the
     96  *     corresponding function and its descendants (not that depending on
     97  *     profile they can be either callees or callers.)
     98  * @param {number} selfTime Amount of time that application spent in the
     99  *     corresponding function only.
    100  * @param {devtools.profiler.ProfileView.Node} head Profile view head.
    101  * @return {devtools.profiler.ProfileView.Node} Profile view node.
    102  */
    103 devtools.profiler.ViewBuilder.prototype.createViewNode = function(
    104     funcName, totalTime, selfTime, head) {
    105   return new devtools.profiler.ProfileView.Node(
    106       funcName, totalTime, selfTime, head);
    107 };
    108 
    109 
    110 /**
    111  * Creates a Profile View object. It allows to perform sorting
    112  * and filtering actions on the profile.
    113  *
    114  * @param {devtools.profiler.ProfileView.Node} head Head (root) node.
    115  * @constructor
    116  */
    117 devtools.profiler.ProfileView = function(head) {
    118   this.head = head;
    119 };
    120 
    121 
    122 /**
    123  * Sorts the profile view using the specified sort function.
    124  *
    125  * @param {function(devtools.profiler.ProfileView.Node,
    126  *     devtools.profiler.ProfileView.Node):number} sortFunc A sorting
    127  *     functions. Must comply with Array.sort sorting function requirements.
    128  */
    129 devtools.profiler.ProfileView.prototype.sort = function(sortFunc) {
    130   this.traverse(function (node) {
    131     node.sortChildren(sortFunc);
    132   });
    133 };
    134 
    135 
    136 /**
    137  * Traverses profile view nodes in preorder.
    138  *
    139  * @param {function(devtools.profiler.ProfileView.Node)} f Visitor function.
    140  */
    141 devtools.profiler.ProfileView.prototype.traverse = function(f) {
    142   var nodesToTraverse = new ConsArray();
    143   nodesToTraverse.concat([this.head]);
    144   while (!nodesToTraverse.atEnd()) {
    145     var node = nodesToTraverse.next();
    146     f(node);
    147     nodesToTraverse.concat(node.children);
    148   }
    149 };
    150 
    151 
    152 /**
    153  * Constructs a Profile View node object. Each node object corresponds to
    154  * a function call.
    155  *
    156  * @param {string} internalFuncName A fully qualified function name.
    157  * @param {number} totalTime Amount of time that application spent in the
    158  *     corresponding function and its descendants (not that depending on
    159  *     profile they can be either callees or callers.)
    160  * @param {number} selfTime Amount of time that application spent in the
    161  *     corresponding function only.
    162  * @param {devtools.profiler.ProfileView.Node} head Profile view head.
    163  * @constructor
    164  */
    165 devtools.profiler.ProfileView.Node = function(
    166     internalFuncName, totalTime, selfTime, head) {
    167   this.internalFuncName = internalFuncName;
    168   this.totalTime = totalTime;
    169   this.selfTime = selfTime;
    170   this.head = head;
    171   this.parent = null;
    172   this.children = [];
    173 };
    174 
    175 
    176 /**
    177  * Returns a share of the function's total time in application's total time.
    178  */
    179 devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
    180     'totalPercent',
    181     function() { return this.totalTime /
    182       (this.head ? this.head.totalTime : this.totalTime) * 100.0; });
    183 
    184 
    185 /**
    186  * Returns a share of the function's self time in application's total time.
    187  */
    188 devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
    189     'selfPercent',
    190     function() { return this.selfTime /
    191       (this.head ? this.head.totalTime : this.totalTime) * 100.0; });
    192 
    193 
    194 /**
    195  * Returns a share of the function's total time in its parent's total time.
    196  */
    197 devtools.profiler.ProfileView.Node.prototype.__defineGetter__(
    198     'parentTotalPercent',
    199     function() { return this.totalTime /
    200       (this.parent ? this.parent.totalTime : this.totalTime) * 100.0; });
    201 
    202 
    203 /**
    204  * Adds a child to the node.
    205  *
    206  * @param {devtools.profiler.ProfileView.Node} node Child node.
    207  */
    208 devtools.profiler.ProfileView.Node.prototype.addChild = function(node) {
    209   node.parent = this;
    210   this.children.push(node);
    211 };
    212 
    213 
    214 /**
    215  * Sorts all the node's children recursively.
    216  *
    217  * @param {function(devtools.profiler.ProfileView.Node,
    218  *     devtools.profiler.ProfileView.Node):number} sortFunc A sorting
    219  *     functions. Must comply with Array.sort sorting function requirements.
    220  */
    221 devtools.profiler.ProfileView.Node.prototype.sortChildren = function(
    222     sortFunc) {
    223   this.children.sort(sortFunc);
    224 };
    225