xhprof_report.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* Copyright (c) 2009 Facebook
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. /**
  16. * Helper javascript functions for XHProf report tooltips.
  17. *
  18. * @author Kannan Muthukkaruppan
  19. */
  20. // Take a string which is actually a number in comma separated format
  21. // and return a string representing the absolute value of the number.
  22. function stringAbs(x) {
  23. return x.replace("-", "");
  24. }
  25. // Takes a number in comma-separated string format, and
  26. // returns a boolean to indicate if the number is negative
  27. // or not.
  28. function isNegative(x) {
  29. return (x.indexOf("-") == 0);
  30. }
  31. function addCommas(nStr)
  32. {
  33. nStr += '';
  34. x = nStr.split('.');
  35. x1 = x[0];
  36. x2 = x.length > 1 ? '.' + x[1] : '';
  37. var rgx = /(\d+)(\d{3})/;
  38. while (rgx.test(x1)) {
  39. x1 = x1.replace(rgx, '$1' + ',' + '$2');
  40. }
  41. return x1 + x2;
  42. }
  43. // Mouseover tips for parent rows in parent/child report..
  44. function ParentRowToolTip(cell, metric)
  45. {
  46. var metric_val;
  47. var parent_metric_val;
  48. var parent_metric_pct_val;
  49. var col_index;
  50. var diff_text;
  51. row = cell.parentNode;
  52. tds = row.getElementsByTagName("td");
  53. parent_func = tds[0].innerHTML; // name
  54. if (diff_mode) {
  55. diff_text = " diff ";
  56. } else {
  57. diff_text = "";
  58. }
  59. s = '<center>';
  60. if (metric == "ct") {
  61. parent_ct = tds[1].innerHTML; // calls
  62. parent_ct_pct = tds[2].innerHTML;
  63. func_ct = addCommas(func_ct);
  64. if (diff_mode) {
  65. s += 'There are ' + stringAbs(parent_ct) +
  66. (isNegative(parent_ct) ? ' fewer ' : ' more ') +
  67. ' calls to ' + func_name + ' from ' + parent_func + '<br>';
  68. text = " of diff in calls ";
  69. } else {
  70. text = " of calls ";
  71. }
  72. s += parent_ct_pct + text + '(' + parent_ct + '/' + func_ct + ') to '
  73. + func_name + ' are from ' + parent_func + '<br>';
  74. } else {
  75. // help for other metrics such as wall time, user cpu time, memory usage
  76. col_index = metrics_col[metric];
  77. parent_metric_val = tds[col_index].innerHTML;
  78. parent_metric_pct_val = tds[col_index+1].innerHTML;
  79. metric_val = addCommas(func_metrics[metric]);
  80. s += parent_metric_pct_val + '(' + parent_metric_val + '/' + metric_val
  81. + ') of ' + metrics_desc[metric] +
  82. (diff_mode ? ((isNegative(parent_metric_val) ?
  83. " decrease" : " increase")) : "") +
  84. ' in ' + func_name + ' is due to calls from ' + parent_func + '<br>';
  85. }
  86. s += '</center>';
  87. return s;
  88. }
  89. // Mouseover tips for child rows in parent/child report..
  90. function ChildRowToolTip(cell, metric)
  91. {
  92. var metric_val;
  93. var child_metric_val;
  94. var child_metric_pct_val;
  95. var col_index;
  96. var diff_text;
  97. row = cell.parentNode;
  98. tds = row.getElementsByTagName("td");
  99. child_func = tds[0].innerHTML; // name
  100. if (diff_mode) {
  101. diff_text = " diff ";
  102. } else {
  103. diff_text = "";
  104. }
  105. s = '<center>';
  106. if (metric == "ct") {
  107. child_ct = tds[1].innerHTML; // calls
  108. child_ct_pct = tds[2].innerHTML;
  109. s += func_name + ' called ' + child_func + ' ' + stringAbs(child_ct) +
  110. (diff_mode ? (isNegative(child_ct) ? " fewer" : " more") : "" )
  111. + ' times.<br>';
  112. s += 'This accounts for ' + child_ct_pct + ' (' + child_ct
  113. + '/' + total_child_ct
  114. + ') of function calls made by ' + func_name + '.';
  115. } else {
  116. // help for other metrics such as wall time, user cpu time, memory usage
  117. col_index = metrics_col[metric];
  118. child_metric_val = tds[col_index].innerHTML;
  119. child_metric_pct_val = tds[col_index+1].innerHTML;
  120. metric_val = addCommas(func_metrics[metric]);
  121. if (child_func.indexOf("Exclusive Metrics") != -1) {
  122. s += 'The exclusive ' + metrics_desc[metric] + diff_text
  123. + ' for ' + func_name
  124. + ' is ' + child_metric_val + " <br>";
  125. s += "which is " + child_metric_pct_val + " of the inclusive "
  126. + metrics_desc[metric]
  127. + diff_text + " for " + func_name + " (" + metric_val + ").";
  128. } else {
  129. s += child_func + ' when called from ' + func_name
  130. + ' takes ' + stringAbs(child_metric_val)
  131. + (diff_mode ? (isNegative(child_metric_val) ? " less" : " more") : "")
  132. + " of " + metrics_desc[metric] + " <br>";
  133. s += "which is " + child_metric_pct_val + " of the inclusive "
  134. + metrics_desc[metric]
  135. + diff_text + " for " + func_name + " (" + metric_val + ").";
  136. }
  137. }
  138. s += '</center>';
  139. return s;
  140. }
  141. $(document).ready(function() {
  142. $('td[@metric]').tooltip(
  143. { bodyHandler: function() {
  144. var type = $(this).attr('type');
  145. var metric = $(this).attr('metric');
  146. if (type == 'Parent') {
  147. return ParentRowToolTip(this, metric);
  148. } else if (type == 'Child') {
  149. return ChildRowToolTip(this, metric);
  150. }
  151. },
  152. showURL : false
  153. });
  154. var cur_params = {} ;
  155. $.each(location.search.replace('?','').split('&'), function(i, x) {
  156. var y = x.split('='); cur_params[y[0]] = y[1];
  157. });
  158. $('input.function_typeahead')
  159. .autocomplete('typeahead.php', { extraParams : cur_params })
  160. .result(function(event, item) {
  161. cur_params['symbol'] = item;
  162. location.search = '?' + jQuery.param(cur_params);
  163. });
  164. });