Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/xhprof/xhprof_lib/display/xhprof.php
Go to the documentation of this file.
00001 <?php
00002 //  Copyright (c) 2009 Facebook
00003 //
00004 //  Licensed under the Apache License, Version 2.0 (the "License");
00005 //  you may not use this file except in compliance with the License.
00006 //  You may obtain a copy of the License at
00007 //
00008 //      http://www.apache.org/licenses/LICENSE-2.0
00009 //
00010 //  Unless required by applicable law or agreed to in writing, software
00011 //  distributed under the License is distributed on an "AS IS" BASIS,
00012 //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 //  See the License for the specific language governing permissions and
00014 //  limitations under the License.
00015 //
00016 
00017 //
00018 // XHProf: A Hierarchical Profiler for PHP
00019 //
00020 // XHProf has two components:
00021 //
00022 //  * This module is the UI/reporting component, used
00023 //    for viewing results of XHProf runs from a browser.
00024 //
00025 //  * Data collection component: This is implemented
00026 //    as a PHP extension (XHProf).
00027 //
00028 // @author Kannan Muthukkaruppan
00029 //
00030 
00031 if (!isset($GLOBALS['XHPROF_LIB_ROOT'])) {
00032   // by default, the parent directory is XHPROF lib root
00033   $GLOBALS['XHPROF_LIB_ROOT'] = realpath(dirname(__FILE__) . '/..');
00034 }
00035 
00036 require_once $GLOBALS['XHPROF_LIB_ROOT'].'/utils/xhprof_lib.php';
00037 require_once $GLOBALS['XHPROF_LIB_ROOT'].'/utils/callgraph_utils.php';
00038 require_once $GLOBALS['XHPROF_LIB_ROOT'].'/utils/xhprof_runs.php';
00039 
00040 
00045 $base_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), "/");
00046 
00047 
00058 function xhprof_include_js_css($ui_dir_url_path = null) {
00059 
00060   if (empty($ui_dir_url_path)) {
00061     $ui_dir_url_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), "/");
00062   }
00063 
00064   // style sheets
00065   echo "<link href='$ui_dir_url_path/css/xhprof.css' rel='stylesheet' ".
00066     " type='text/css' />";
00067   echo "<link href='$ui_dir_url_path/jquery/jquery.tooltip.css' ".
00068     " rel='stylesheet' type='text/css' />";
00069   echo "<link href='$ui_dir_url_path/jquery/jquery.autocomplete.css' ".
00070     " rel='stylesheet' type='text/css' />";
00071 
00072   // javascript
00073   echo "<script src='$ui_dir_url_path/jquery/jquery-1.2.6.js'>".
00074        "</script>";
00075   echo "<script src='$ui_dir_url_path/jquery/jquery.tooltip.js'>".
00076        "</script>";
00077   echo "<script src='$ui_dir_url_path/jquery/jquery.autocomplete.js'>"
00078        ."</script>";
00079   echo "<script src='$ui_dir_url_path/js/xhprof_report.js'></script>";
00080 }
00081 
00082 
00083 /*
00084  * Formats call counts for XHProf reports.
00085  *
00086  * Description:
00087  * Call counts in single-run reports are integer values.
00088  * However, call counts for aggregated reports can be
00089  * fractional. This function will print integer values
00090  * without decimal point, but with commas etc.
00091  *
00092  *   4000 ==> 4,000
00093  *
00094  * It'll round fractional values to decimal precision of 3
00095  *   4000.1212 ==> 4,000.121
00096  *   4000.0001 ==> 4,000
00097  *
00098  */
00099 function xhprof_count_format($num) {
00100   $num = round($num, 3);
00101   if (round($num) == $num) {
00102     return number_format($num);
00103   } else {
00104     return number_format($num, 3);
00105   }
00106 }
00107 
00108 function xhprof_percent_format($s, $precision = 1) {
00109   return sprintf('%.'.$precision.'f%%', 100 * $s);
00110 }
00111 
00116 function xhprof_render_actions($actions) {
00117   $out = array();
00118 
00119   if (count($actions)) {
00120     $out[] = '<ul class="xhprof_actions">';
00121     foreach ($actions as $action) {
00122       $out[] = '<li>'.$action.'</li>';
00123     }
00124     $out[] = '</ul>';
00125   }
00126 
00127   return implode('', $out);
00128 }
00129 
00130 
00147 function xhprof_render_link($content, $href, $class='', $id='', $title='',
00148                             $target='',
00149                             $onclick='', $style='', $access='', $onmouseover='',
00150                             $onmouseout='', $onmousedown='') {
00151 
00152   if (!$content) {
00153     return '';
00154   }
00155 
00156   if ($href) {
00157     $link = '<a href="' . ($href) . '"';
00158   } else {
00159     $link = '<span';
00160   }
00161 
00162   if ($class) {
00163     $link .= ' class="' . ($class) . '"';
00164   }
00165   if ($id) {
00166     $link .= ' id="' . ($id) . '"';
00167   }
00168   if ($title) {
00169     $link .= ' title="' . ($title) . '"';
00170   }
00171   if ($target) {
00172     $link .= ' target="' . ($target) . '"';
00173   }
00174   if ($onclick && $href) {
00175     $link .= ' onclick="' . ($onclick) . '"';
00176   }
00177   if ($style && $href) {
00178     $link .= ' style="' . ($style) . '"';
00179   }
00180   if ($access && $href) {
00181     $link .= ' accesskey="' . ($access) . '"';
00182   }
00183   if ($onmouseover) {
00184     $link .= ' onmouseover="' . ($onmouseover) . '"';
00185   }
00186   if ($onmouseout) {
00187     $link .= ' onmouseout="' . ($onmouseout) . '"';
00188   }
00189   if ($onmousedown) {
00190     $link .= ' onmousedown="' . ($onmousedown) . '"';
00191   }
00192 
00193   $link .= '>';
00194   $link .= $content;
00195   if ($href) {
00196     $link .= '</a>';
00197   } else {
00198     $link .= '</span>';
00199   }
00200 
00201   return $link;
00202 }
00203 
00204 
00205 // default column to sort on -- wall time
00206 $sort_col = "wt";
00207 
00208 // default is "single run" report
00209 $diff_mode = false;
00210 
00211 // call count data present?
00212 $display_calls = true;
00213 
00214 // The following column headers are sortable
00215 $sortable_columns = array("fn" => 1,
00216                           "ct" => 1,
00217                           "wt" => 1,
00218                           "excl_wt" => 1,
00219                           "ut" => 1,
00220                           "excl_ut" => 1,
00221                           "st" => 1,
00222                           "excl_st" => 1,
00223                           "mu" => 1,
00224                           "excl_mu" => 1,
00225                           "pmu" => 1,
00226                           "excl_pmu" => 1,
00227                           "cpu" => 1,
00228                           "excl_cpu" => 1,
00229                           "samples" => 1,
00230                           "excl_samples" => 1
00231                           );
00232 
00233 // Textual descriptions for column headers in "single run" mode
00234 $descriptions = array(
00235                       "fn" => "Function Name",
00236                       "ct" =>  "Calls",
00237                       "Calls%" => "Calls%",
00238 
00239                       "wt" => "Incl. Wall Time<br>(microsec)",
00240                       "IWall%" => "IWall%",
00241                       "excl_wt" => "Excl. Wall Time<br>(microsec)",
00242                       "EWall%" => "EWall%",
00243 
00244                       "ut" => "Incl. User<br>(microsecs)",
00245                       "IUser%" => "IUser%",
00246                       "excl_ut" => "Excl. User<br>(microsec)",
00247                       "EUser%" => "EUser%",
00248 
00249                       "st" => "Incl. Sys <br>(microsec)",
00250                       "ISys%" => "ISys%",
00251                       "excl_st" => "Excl. Sys <br>(microsec)",
00252                       "ESys%" => "ESys%",
00253 
00254                       "cpu" => "Incl. CPU<br>(microsecs)",
00255                       "ICpu%" => "ICpu%",
00256                       "excl_cpu" => "Excl. CPU<br>(microsec)",
00257                       "ECpu%" => "ECPU%",
00258 
00259                       "mu" => "Incl.<br>MemUse<br>(bytes)",
00260                       "IMUse%" => "IMemUse%",
00261                       "excl_mu" => "Excl.<br>MemUse<br>(bytes)",
00262                       "EMUse%" => "EMemUse%",
00263 
00264                       "pmu" => "Incl.<br> PeakMemUse<br>(bytes)",
00265                       "IPMUse%" => "IPeakMemUse%",
00266                       "excl_pmu" => "Excl.<br>PeakMemUse<br>(bytes)",
00267                       "EPMUse%" => "EPeakMemUse%",
00268 
00269                       "samples" => "Incl. Samples",
00270                       "ISamples%" => "ISamples%",
00271                       "excl_samples" => "Excl. Samples",
00272                       "ESamples%" => "ESamples%",
00273                       );
00274 
00275 // Formatting Callback Functions...
00276 $format_cbk = array(
00277                       "fn" => "",
00278                       "ct" => "xhprof_count_format",
00279                       "Calls%" => "xhprof_percent_format",
00280 
00281                       "wt" => "number_format",
00282                       "IWall%" => "xhprof_percent_format",
00283                       "excl_wt" => "number_format",
00284                       "EWall%" => "xhprof_percent_format",
00285 
00286                       "ut" => "number_format",
00287                       "IUser%" => "xhprof_percent_format",
00288                       "excl_ut" => "number_format",
00289                       "EUser%" => "xhprof_percent_format",
00290 
00291                       "st" => "number_format",
00292                       "ISys%" => "xhprof_percent_format",
00293                       "excl_st" => "number_format",
00294                       "ESys%" => "xhprof_percent_format",
00295 
00296                       "cpu" => "number_format",
00297                       "ICpu%" => "xhprof_percent_format",
00298                       "excl_cpu" => "number_format",
00299                       "ECpu%" => "xhprof_percent_format",
00300 
00301                       "mu" => "number_format",
00302                       "IMUse%" => "xhprof_percent_format",
00303                       "excl_mu" => "number_format",
00304                       "EMUse%" => "xhprof_percent_format",
00305 
00306                       "pmu" => "number_format",
00307                       "IPMUse%" => "xhprof_percent_format",
00308                       "excl_pmu" => "number_format",
00309                       "EPMUse%" => "xhprof_percent_format",
00310 
00311                       "samples" => "number_format",
00312                       "ISamples%" => "xhprof_percent_format",
00313                       "excl_samples" => "number_format",
00314                       "ESamples%" => "xhprof_percent_format",
00315                       );
00316 
00317 
00318 // Textual descriptions for column headers in "diff" mode
00319 $diff_descriptions = array(
00320                       "fn" => "Function Name",
00321                       "ct" =>  "Calls Diff",
00322                       "Calls%" => "Calls<br>Diff%",
00323 
00324                       "wt" => "Incl. Wall<br>Diff<br>(microsec)",
00325                       "IWall%" => "IWall<br> Diff%",
00326                       "excl_wt" => "Excl. Wall<br>Diff<br>(microsec)",
00327                       "EWall%" => "EWall<br>Diff%",
00328 
00329                       "ut" => "Incl. User Diff<br>(microsec)",
00330                       "IUser%" => "IUser<br>Diff%",
00331                       "excl_ut" => "Excl. User<br>Diff<br>(microsec)",
00332                       "EUser%" => "EUser<br>Diff%",
00333 
00334                       "cpu" => "Incl. CPU Diff<br>(microsec)",
00335                       "ICpu%" => "ICpu<br>Diff%",
00336                       "excl_cpu" => "Excl. CPU<br>Diff<br>(microsec)",
00337                       "ECpu%" => "ECpu<br>Diff%",
00338 
00339                       "st" => "Incl. Sys Diff<br>(microsec)",
00340                       "ISys%" => "ISys<br>Diff%",
00341                       "excl_st" => "Excl. Sys Diff<br>(microsec)",
00342                       "ESys%" => "ESys<br>Diff%",
00343 
00344                       "mu" => "Incl.<br>MemUse<br>Diff<br>(bytes)",
00345                       "IMUse%" => "IMemUse<br>Diff%",
00346                       "excl_mu" => "Excl.<br>MemUse<br>Diff<br>(bytes)",
00347                       "EMUse%" => "EMemUse<br>Diff%",
00348 
00349                       "pmu" => "Incl.<br> PeakMemUse<br>Diff<br>(bytes)",
00350                       "IPMUse%" => "IPeakMemUse<br>Diff%",
00351                       "excl_pmu" => "Excl.<br>PeakMemUse<br>Diff<br>(bytes)",
00352                       "EPMUse%" => "EPeakMemUse<br>Diff%",
00353 
00354                       "samples" => "Incl. Samples Diff",
00355                       "ISamples%" => "ISamples Diff%",
00356                       "excl_samples" => "Excl. Samples Diff",
00357                       "ESamples%" => "ESamples Diff%",
00358                       );
00359 
00360 // columns that'll be displayed in a top-level report
00361 $stats = array();
00362 
00363 // columns that'll be displayed in a function's parent/child report
00364 $pc_stats = array();
00365 
00366 // Various total counts
00367 $totals = 0;
00368 $totals_1 = 0;
00369 $totals_2 = 0;
00370 
00371 /*
00372  * The subset of $possible_metrics that is present in the raw profile data.
00373  */
00374 $metrics = null;
00375 
00383 function sort_cbk($a, $b) {
00384   global $sort_col;
00385   global $diff_mode;
00386 
00387   if ($sort_col == "fn") {
00388 
00389     // case insensitive ascending sort for function names
00390     $left = strtoupper($a["fn"]);
00391     $right = strtoupper($b["fn"]);
00392 
00393     if ($left == $right)
00394       return 0;
00395     return ($left < $right) ? -1 : 1;
00396 
00397   } else {
00398 
00399     // descending sort for all others
00400     $left = $a[$sort_col];
00401     $right = $b[$sort_col];
00402 
00403     // if diff mode, sort by absolute value of regression/improvement
00404     if ($diff_mode) {
00405       $left = abs($left);
00406       $right = abs($right);
00407     }
00408 
00409     if ($left == $right)
00410       return 0;
00411     return ($left > $right) ? -1 : 1;
00412   }
00413 }
00414 
00422 function stat_description($stat) {
00423   global $descriptions;
00424   global $diff_descriptions;
00425   global $diff_mode;
00426 
00427   if ($diff_mode) {
00428     return $diff_descriptions[$stat];
00429   } else {
00430     return $descriptions[$stat];
00431   }
00432 }
00433 
00434 
00441 function profiler_report ($url_params,
00442                           $rep_symbol,
00443                           $sort,
00444                           $run1,
00445                           $run1_desc,
00446                           $run1_data,
00447                           $run2 = 0,
00448                           $run2_desc = "",
00449                           $run2_data = array()) {
00450   global $totals;
00451   global $totals_1;
00452   global $totals_2;
00453   global $stats;
00454   global $pc_stats;
00455   global $diff_mode;
00456   global $base_path;
00457 
00458   // if we are reporting on a specific function, we can trim down
00459   // the report(s) to just stuff that is relevant to this function.
00460   // That way compute_flat_info()/compute_diff() etc. do not have
00461   // to needlessly work hard on churning irrelevant data.
00462   if (!empty($rep_symbol)) {
00463     $run1_data = xhprof_trim_run($run1_data, array($rep_symbol));
00464     if ($diff_mode) {
00465       $run2_data = xhprof_trim_run($run2_data, array($rep_symbol));
00466     }
00467   }
00468 
00469   if ($diff_mode) {
00470     $run_delta = xhprof_compute_diff($run1_data, $run2_data);
00471     $symbol_tab  = xhprof_compute_flat_info($run_delta, $totals);
00472     $symbol_tab1 = xhprof_compute_flat_info($run1_data, $totals_1);
00473     $symbol_tab2 = xhprof_compute_flat_info($run2_data, $totals_2);
00474   } else {
00475     $symbol_tab = xhprof_compute_flat_info($run1_data, $totals);
00476   }
00477 
00478   $run1_txt = sprintf("<b>Run #%s:</b> %s",
00479                       $run1, $run1_desc);
00480 
00481   $base_url_params = xhprof_array_unset(xhprof_array_unset($url_params,
00482                                                            'symbol'),
00483                                         'all');
00484 
00485   $top_link_query_string = "$base_path/?" . http_build_query($base_url_params);
00486 
00487   if ($diff_mode) {
00488     $diff_text = "Diff";
00489     $base_url_params = xhprof_array_unset($base_url_params, 'run1');
00490     $base_url_params = xhprof_array_unset($base_url_params, 'run2');
00491     $run1_link = xhprof_render_link('View Run #' . $run1,
00492                            "$base_path/?" .
00493                            http_build_query(xhprof_array_set($base_url_params,
00494                                                       'run',
00495                                                       $run1)));
00496     $run2_txt = sprintf("<b>Run #%s:</b> %s",
00497                         $run2, $run2_desc);
00498 
00499     $run2_link = xhprof_render_link('View Run #' . $run2,
00500                                     "$base_path/?" .
00501                         http_build_query(xhprof_array_set($base_url_params,
00502                                                           'run',
00503                                                           $run2)));
00504   } else {
00505     $diff_text = "Run";
00506   }
00507 
00508   // set up the action links for operations that can be done on this report
00509   $links = array();
00510   $links [] =  xhprof_render_link("View Top Level $diff_text Report",
00511                                  $top_link_query_string);
00512 
00513   if ($diff_mode) {
00514     $inverted_params = $url_params;
00515     $inverted_params['run1'] = $url_params['run2'];
00516     $inverted_params['run2'] = $url_params['run1'];
00517 
00518     // view the different runs or invert the current diff
00519     $links [] = $run1_link;
00520     $links [] = $run2_link;
00521     $links [] = xhprof_render_link('Invert ' . $diff_text . ' Report',
00522                            "$base_path/?".
00523                            http_build_query($inverted_params));
00524   }
00525 
00526   // lookup function typeahead form
00527   $links [] = '<input class="function_typeahead" ' .
00528               ' type="input" size="40" maxlength="100" />';
00529 
00530   echo xhprof_render_actions($links);
00531 
00532 
00533   echo
00534     '<dl class=phprof_report_info>' .
00535     '  <dt>' . $diff_text . ' Report</dt>' .
00536     '  <dd>' . ($diff_mode ?
00537                 $run1_txt . '<br><b>vs.</b><br>' . $run2_txt :
00538                 $run1_txt) .
00539     '  </dd>' .
00540     '  <dt>Tip</dt>' .
00541     '  <dd>Click a function name below to drill down.</dd>' .
00542     '</dl>' .
00543     '<div style="clear: both; margin: 3em 0em;"></div>';
00544 
00545   // data tables
00546   if (!empty($rep_symbol)) {
00547     if (!isset($symbol_tab[$rep_symbol])) {
00548       echo "<hr>Symbol <b>$rep_symbol</b> not found in XHProf run</b><hr>";
00549       return;
00550     }
00551 
00552     /* single function report with parent/child information */
00553     if ($diff_mode) {
00554       $info1 = isset($symbol_tab1[$rep_symbol]) ?
00555                        $symbol_tab1[$rep_symbol] : null;
00556       $info2 = isset($symbol_tab2[$rep_symbol]) ?
00557                        $symbol_tab2[$rep_symbol] : null;
00558       symbol_report($url_params, $run_delta, $symbol_tab[$rep_symbol],
00559                     $sort, $rep_symbol,
00560                     $run1, $info1,
00561                     $run2, $info2);
00562     } else {
00563       symbol_report($url_params, $run1_data, $symbol_tab[$rep_symbol],
00564                     $sort, $rep_symbol, $run1);
00565     }
00566   } else {
00567     /* flat top-level report of all functions */
00568     full_report($url_params, $symbol_tab, $sort, $run1, $run2);
00569   }
00570 }
00571 
00576 function pct($a, $b) {
00577   if ($b == 0) {
00578     return "N/A";
00579   } else {
00580     $res = (round(($a * 1000 / $b)) / 10);
00581     return $res;
00582   }
00583 }
00584 
00592 function get_print_class($num, $bold) {
00593   global $vbar;
00594   global $vbbar;
00595   global $vrbar;
00596   global $vgbar;
00597   global $diff_mode;
00598 
00599   if ($bold) {
00600     if ($diff_mode) {
00601       if ($num <= 0) {
00602         $class = $vgbar; // green (improvement)
00603       } else {
00604         $class = $vrbar; // red (regression)
00605       }
00606     } else {
00607       $class = $vbbar; // blue
00608     }
00609   }
00610   else {
00611     $class = $vbar;  // default (black)
00612   }
00613 
00614   return $class;
00615 }
00616 
00620 function print_td_num($num, $fmt_func, $bold=false, $attributes=null) {
00621 
00622   $class = get_print_class($num, $bold);
00623 
00624   if (!empty($fmt_func)) {
00625     $num = call_user_func($fmt_func, $num);
00626   }
00627 
00628   print("<td $attributes $class>$num</td>\n");
00629 }
00630 
00634 function print_td_pct($numer, $denom, $bold=false, $attributes=null) {
00635   global $vbar;
00636   global $vbbar;
00637   global $diff_mode;
00638 
00639   $class = get_print_class($numer, $bold);
00640 
00641   if ($denom == 0) {
00642     $pct = "N/A%";
00643   } else {
00644     $pct = xhprof_percent_format($numer / abs($denom));
00645   }
00646 
00647   print("<td $attributes $class>$pct</td>\n");
00648 }
00649 
00655 function print_function_info($url_params, $info, $sort, $run1, $run2) {
00656   static $odd_even = 0;
00657 
00658   global $totals;
00659   global $sort_col;
00660   global $metrics;
00661   global $format_cbk;
00662   global $display_calls;
00663   global $base_path;
00664 
00665   // Toggle $odd_or_even
00666   $odd_even = 1 - $odd_even;
00667 
00668   if ($odd_even) {
00669     print("<tr>");
00670   }
00671   else {
00672     print('<tr bgcolor="#e5e5e5">');
00673   }
00674 
00675   $href = "$base_path/?" .
00676            http_build_query(xhprof_array_set($url_params,
00677                                              'symbol', $info["fn"]));
00678 
00679   print('<td>');
00680   print(xhprof_render_link($info["fn"], $href));
00681   print_source_link($info);
00682   print("</td>\n");
00683 
00684   if ($display_calls) {
00685     // Call Count..
00686     print_td_num($info["ct"], $format_cbk["ct"], ($sort_col == "ct"));
00687     print_td_pct($info["ct"], $totals["ct"], ($sort_col == "ct"));
00688   }
00689 
00690   // Other metrics..
00691   foreach ($metrics as $metric) {
00692     // Inclusive metric
00693     print_td_num($info[$metric], $format_cbk[$metric],
00694                  ($sort_col == $metric));
00695     print_td_pct($info[$metric], $totals[$metric],
00696                  ($sort_col == $metric));
00697 
00698     // Exclusive Metric
00699     print_td_num($info["excl_" . $metric],
00700                  $format_cbk["excl_" . $metric],
00701                  ($sort_col == "excl_" . $metric));
00702     print_td_pct($info["excl_" . $metric],
00703                  $totals[$metric],
00704                  ($sort_col == "excl_" . $metric));
00705   }
00706 
00707   print("</tr>\n");
00708 }
00709 
00715 function print_flat_data($url_params, $title, $flat_data, $sort, $run1, $run2, $limit) {
00716 
00717   global $stats;
00718   global $sortable_columns;
00719   global $vwbar;
00720   global $base_path;
00721 
00722   $size  = count($flat_data);
00723   if (!$limit) {              // no limit
00724     $limit = $size;
00725     $display_link = "";
00726   } else {
00727     $display_link = xhprof_render_link(" [ <b class=bubble>display all </b>]",
00728                                        "$base_path/?" .
00729                                        http_build_query(xhprof_array_set($url_params,
00730                                                                          'all', 1)));
00731   }
00732 
00733   print("<h3 align=center>$title $display_link</h3><br>");
00734 
00735   print('<table border=1 cellpadding=2 cellspacing=1 width="90%" '
00736         .'rules=rows bordercolor="#bdc7d8" align=center>');
00737   print('<tr bgcolor="#bdc7d8" align=right>');
00738 
00739   foreach ($stats as $stat) {
00740     $desc = stat_description($stat);
00741     if (array_key_exists($stat, $sortable_columns)) {
00742       $href = "$base_path/?"
00743               . http_build_query(xhprof_array_set($url_params, 'sort', $stat));
00744       $header = xhprof_render_link($desc, $href);
00745     } else {
00746       $header = $desc;
00747     }
00748 
00749     if ($stat == "fn")
00750       print("<th align=left><nobr>$header</th>");
00751     else print("<th " . $vwbar . "><nobr>$header</th>");
00752   }
00753   print("</tr>\n");
00754 
00755   if ($limit >= 0) {
00756     $limit = min($size, $limit);
00757     for ($i = 0; $i < $limit; $i++) {
00758       print_function_info($url_params, $flat_data[$i], $sort, $run1, $run2);
00759     }
00760   } else {
00761     // if $limit is negative, print abs($limit) items starting from the end
00762     $limit = min($size, abs($limit));
00763     for ($i = 0; $i < $limit; $i++) {
00764       print_function_info($url_params, $flat_data[$size - $i - 1], $sort, $run1, $run2);
00765     }
00766   }
00767   print("</table>");
00768 
00769   // let's print the display all link at the bottom as well...
00770   if ($display_link) {
00771     echo '<div style="text-align: left; padding: 2em">' . $display_link . '</div>';
00772   }
00773 
00774 }
00775 
00781 function full_report($url_params, $symbol_tab, $sort, $run1, $run2) {
00782   global $vwbar;
00783   global $vbar;
00784   global $totals;
00785   global $totals_1;
00786   global $totals_2;
00787   global $metrics;
00788   global $diff_mode;
00789   global $descriptions;
00790   global $sort_col;
00791   global $format_cbk;
00792   global $display_calls;
00793   global $base_path;
00794 
00795   $possible_metrics = xhprof_get_possible_metrics();
00796 
00797   if ($diff_mode) {
00798 
00799     $base_url_params = xhprof_array_unset(xhprof_array_unset($url_params,
00800                                                              'run1'),
00801                                           'run2');
00802     $href1 = "$base_path/?" .
00803       http_build_query(xhprof_array_set($base_url_params,
00804                                         'run', $run1));
00805     $href2 = "$base_path/?" .
00806       http_build_query(xhprof_array_set($base_url_params,
00807                                         'run', $run2));
00808 
00809     print("<h3><center>Overall Diff Summary</center></h3>");
00810     print('<table border=1 cellpadding=2 cellspacing=1 width="30%" '
00811           .'rules=rows bordercolor="#bdc7d8" align=center>' . "\n");
00812     print('<tr bgcolor="#bdc7d8" align=right>');
00813     print("<th></th>");
00814     print("<th $vwbar>" . xhprof_render_link("Run #$run1", $href1) . "</th>");
00815     print("<th $vwbar>" . xhprof_render_link("Run #$run2", $href2) . "</th>");
00816     print("<th $vwbar>Diff</th>");
00817     print("<th $vwbar>Diff%</th>");
00818     print('</tr>');
00819 
00820     if ($display_calls) {
00821       print('<tr>');
00822       print("<td>Number of Function Calls</td>");
00823       print_td_num($totals_1["ct"], $format_cbk["ct"]);
00824       print_td_num($totals_2["ct"], $format_cbk["ct"]);
00825       print_td_num($totals_2["ct"] - $totals_1["ct"], $format_cbk["ct"], true);
00826       print_td_pct($totals_2["ct"] - $totals_1["ct"], $totals_1["ct"], true);
00827       print('</tr>');
00828     }
00829 
00830     foreach ($metrics as $metric) {
00831       $m = $metric;
00832       print('<tr>');
00833       print("<td>" . str_replace("<br>", " ", $descriptions[$m]) . "</td>");
00834       print_td_num($totals_1[$m], $format_cbk[$m]);
00835       print_td_num($totals_2[$m], $format_cbk[$m]);
00836       print_td_num($totals_2[$m] - $totals_1[$m], $format_cbk[$m], true);
00837       print_td_pct($totals_2[$m] - $totals_1[$m], $totals_1[$m], true);
00838       print('<tr>');
00839     }
00840     print('</table>');
00841 
00842     $callgraph_report_title = '[View Regressions/Improvements using Callgraph Diff]';
00843 
00844   } else {
00845     print("<p><center>\n");
00846 
00847     print('<table cellpadding=2 cellspacing=1 width="30%" '
00848           .'bgcolor="#bdc7d8" align=center>' . "\n");
00849     echo "<tr>";
00850     echo "<th style='text-align:right'>Overall Summary</th>";
00851     echo "<th></th>";
00852     echo "</tr>";
00853 
00854     foreach ($metrics as $metric) {
00855       echo "<tr>";
00856       echo "<td style='text-align:right; font-weight:bold'>Total "
00857             . str_replace("<br>", " ", stat_description($metric)) . ":</td>";
00858       echo "<td>" . number_format($totals[$metric]) .  " "
00859            . $possible_metrics[$metric][1] . "</td>";
00860       echo "</tr>";
00861     }
00862 
00863     if ($display_calls) {
00864       echo "<tr>";
00865       echo "<td style='text-align:right; font-weight:bold'>Number of Function Calls:</td>";
00866       echo "<td>" . number_format($totals['ct']) . "</td>";
00867       echo "</tr>";
00868     }
00869 
00870     echo "</table>";
00871     print("</center></p>\n");
00872 
00873     $callgraph_report_title = '[View Full Callgraph]';
00874   }
00875 
00876   print("<center><br><h3>" .
00877         xhprof_render_link($callgraph_report_title,
00878                     "$base_path/callgraph.php" . "?" . http_build_query($url_params))
00879         . "</h3></center>");
00880 
00881 
00882   $flat_data = array();
00883   foreach ($symbol_tab as $symbol => $info) {
00884     $tmp = $info;
00885     $tmp["fn"] = $symbol;
00886     $flat_data[] = $tmp;
00887   }
00888   usort($flat_data, 'sort_cbk');
00889 
00890   print("<br>");
00891 
00892   if (!empty($url_params['all'])) {
00893     $all = true;
00894     $limit = 0;    // display all rows
00895   } else {
00896     $all = false;
00897     $limit = 100;  // display only limited number of rows
00898   }
00899 
00900   $desc = str_replace("<br>", " ", $descriptions[$sort_col]);
00901 
00902   if ($diff_mode) {
00903     if ($all) {
00904       $title = "Total Diff Report: '
00905                .'Sorted by absolute value of regression/improvement in $desc";
00906     } else {
00907       $title = "Top 100 <i style='color:red'>Regressions</i>/"
00908                . "<i style='color:green'>Improvements</i>: "
00909                . "Sorted by $desc Diff";
00910     }
00911   } else {
00912     if ($all) {
00913       $title = "Sorted by $desc";
00914     } else {
00915       $title = "Displaying top $limit functions: Sorted by $desc";
00916     }
00917   }
00918   print_flat_data($url_params, $title, $flat_data, $sort, $run1, $run2, $limit);
00919 }
00920 
00921 
00925 function get_tooltip_attributes($type, $metric) {
00926   return "type='$type' metric='$metric'";
00927 }
00928 
00935 function pc_info($info, $base_ct, $base_info, $parent) {
00936   global $sort_col;
00937   global $metrics;
00938   global $format_cbk;
00939   global $display_calls;
00940 
00941   if ($parent)
00942     $type = "Parent";
00943   else $type = "Child";
00944 
00945   if ($display_calls) {
00946     $mouseoverct = get_tooltip_attributes($type, "ct");
00947     /* call count */
00948     print_td_num($info["ct"], $format_cbk["ct"], ($sort_col == "ct"), $mouseoverct);
00949     print_td_pct($info["ct"], $base_ct, ($sort_col == "ct"), $mouseoverct);
00950   }
00951 
00952   /* Inclusive metric values  */
00953   foreach ($metrics as $metric) {
00954     print_td_num($info[$metric], $format_cbk[$metric],
00955                  ($sort_col == $metric),
00956                  get_tooltip_attributes($type, $metric));
00957     print_td_pct($info[$metric], $base_info[$metric], ($sort_col == $metric),
00958                  get_tooltip_attributes($type, $metric));
00959   }
00960 }
00961 
00962 function print_pc_array($url_params, $results, $base_ct, $base_info, $parent,
00963                         $run1, $run2) {
00964   global $base_path;
00965 
00966   // Construct section title
00967   if ($parent) {
00968     $title = 'Parent function';
00969   }
00970   else {
00971     $title = 'Child function';
00972   }
00973   if (count($results) > 1) {
00974     $title .= 's';
00975   }
00976 
00977   print("<tr bgcolor='#e0e0ff'><td>");
00978   print("<b><i><center>" . $title . "</center></i></b>");
00979   print("</td></tr>");
00980 
00981   $odd_even = 0;
00982   foreach ($results as $info) {
00983     $href = "$base_path/?" .
00984       http_build_query(xhprof_array_set($url_params,
00985                                         'symbol', $info["fn"]));
00986 
00987     $odd_even = 1 - $odd_even;
00988 
00989     if ($odd_even) {
00990       print('<tr>');
00991     }
00992     else {
00993       print('<tr bgcolor="#e5e5e5">');
00994     }
00995 
00996     print("<td>" . xhprof_render_link($info["fn"], $href));
00997     print_source_link($info);
00998     print("</td>");
00999     pc_info($info, $base_ct, $base_info, $parent);
01000     print("</tr>");
01001   }
01002 }
01003 
01004 function print_source_link($info) {
01005   if (strncmp($info['fn'], 'run_init', 8) && $info['fn'] !== 'main()') {
01006         if (defined('XHPROF_SYMBOL_LOOKUP_URL')) {
01007       $link = xhprof_render_link(
01008         'source',
01009         XHPROF_SYMBOL_LOOKUP_URL . '?symbol='.rawurlencode($info["fn"]));
01010       print(' ('.$link.')');
01011     }
01012   }
01013 }
01014 
01015 
01016 function print_symbol_summary($symbol_info, $stat, $base) {
01017 
01018   $val = $symbol_info[$stat];
01019   $desc = str_replace("<br>", " ", stat_description($stat));
01020 
01021   print("$desc: </td>");
01022   print(number_format($val));
01023   print(" (" . pct($val, $base) . "% of overall)");
01024   if (substr($stat, 0, 4) == "excl") {
01025     $func_base = $symbol_info[str_replace("excl_", "", $stat)];
01026     print(" (" . pct($val, $func_base) . "% of this function)");
01027   }
01028   print("<br>");
01029 }
01030 
01036 function symbol_report($url_params,
01037                        $run_data, $symbol_info, $sort, $rep_symbol,
01038                        $run1,
01039                        $symbol_info1 = null,
01040                        $run2 = 0,
01041                        $symbol_info2 = null) {
01042   global $vwbar;
01043   global $vbar;
01044   global $totals;
01045   global $pc_stats;
01046   global $sortable_columns;
01047   global $metrics;
01048   global $diff_mode;
01049   global $descriptions;
01050   global $format_cbk;
01051   global $sort_col;
01052   global $display_calls;
01053   global $base_path;
01054 
01055   $possible_metrics = xhprof_get_possible_metrics();
01056 
01057   if ($diff_mode) {
01058     $diff_text = "<b>Diff</b>";
01059     $regr_impr = "<i style='color:red'>Regression</i>/<i style='color:green'>Improvement</i>";
01060   } else {
01061     $diff_text = "";
01062     $regr_impr = "";
01063   }
01064 
01065   if ($diff_mode) {
01066 
01067     $base_url_params = xhprof_array_unset(xhprof_array_unset($url_params,
01068                                                              'run1'),
01069                                           'run2');
01070     $href1 = "$base_path?"
01071       . http_build_query(xhprof_array_set($base_url_params, 'run', $run1));
01072     $href2 = "$base_path?"
01073       . http_build_query(xhprof_array_set($base_url_params, 'run', $run2));
01074 
01075     print("<h3 align=center>$regr_impr summary for $rep_symbol<br><br></h3>");
01076     print('<table border=1 cellpadding=2 cellspacing=1 width="30%" '
01077           .'rules=rows bordercolor="#bdc7d8" align=center>' . "\n");
01078     print('<tr bgcolor="#bdc7d8" align=right>');
01079     print("<th align=left>$rep_symbol</th>");
01080     print("<th $vwbar><a href=" . $href1 . ">Run #$run1</a></th>");
01081     print("<th $vwbar><a href=" . $href2 . ">Run #$run2</a></th>");
01082     print("<th $vwbar>Diff</th>");
01083     print("<th $vwbar>Diff%</th>");
01084     print('</tr>');
01085     print('<tr>');
01086 
01087     if ($display_calls) {
01088       print("<td>Number of Function Calls</td>");
01089       print_td_num($symbol_info1["ct"], $format_cbk["ct"]);
01090       print_td_num($symbol_info2["ct"], $format_cbk["ct"]);
01091       print_td_num($symbol_info2["ct"] - $symbol_info1["ct"],
01092                    $format_cbk["ct"], true);
01093       print_td_pct($symbol_info2["ct"] - $symbol_info1["ct"],
01094                    $symbol_info1["ct"], true);
01095       print('</tr>');
01096     }
01097 
01098 
01099     foreach ($metrics as $metric) {
01100       $m = $metric;
01101 
01102       // Inclusive stat for metric
01103       print('<tr>');
01104       print("<td>" . str_replace("<br>", " ", $descriptions[$m]) . "</td>");
01105       print_td_num($symbol_info1[$m], $format_cbk[$m]);
01106       print_td_num($symbol_info2[$m], $format_cbk[$m]);
01107       print_td_num($symbol_info2[$m] - $symbol_info1[$m], $format_cbk[$m], true);
01108       print_td_pct($symbol_info2[$m] - $symbol_info1[$m], $symbol_info1[$m], true);
01109       print('</tr>');
01110 
01111       // AVG (per call) Inclusive stat for metric
01112       print('<tr>');
01113       print("<td>" . str_replace("<br>", " ", $descriptions[$m]) . " per call </td>");
01114       $avg_info1 = 'N/A';
01115       $avg_info2 = 'N/A';
01116       if ($symbol_info1['ct'] > 0) {
01117         $avg_info1 = ($symbol_info1[$m] / $symbol_info1['ct']);
01118       }
01119       if ($symbol_info2['ct'] > 0) {
01120         $avg_info2 = ($symbol_info2[$m] / $symbol_info2['ct']);
01121       }
01122       print_td_num($avg_info1, $format_cbk[$m]);
01123       print_td_num($avg_info2, $format_cbk[$m]);
01124       print_td_num($avg_info2 - $avg_info1, $format_cbk[$m], true);
01125       print_td_pct($avg_info2 - $avg_info1, $avg_info1, true);
01126       print('</tr>');
01127 
01128       // Exclusive stat for metric
01129       $m = "excl_" . $metric;
01130       print('<tr style="border-bottom: 1px solid black;">');
01131       print("<td>" . str_replace("<br>", " ", $descriptions[$m]) . "</td>");
01132       print_td_num($symbol_info1[$m], $format_cbk[$m]);
01133       print_td_num($symbol_info2[$m], $format_cbk[$m]);
01134       print_td_num($symbol_info2[$m] - $symbol_info1[$m], $format_cbk[$m], true);
01135       print_td_pct($symbol_info2[$m] - $symbol_info1[$m], $symbol_info1[$m], true);
01136       print('</tr>');
01137     }
01138 
01139     print('</table>');
01140   }
01141 
01142   print("<br><h4><center>");
01143   print("Parent/Child $regr_impr report for <b>$rep_symbol</b>");
01144 
01145   $callgraph_href = "$base_path/callgraph.php?"
01146     . http_build_query(xhprof_array_set($url_params, 'func', $rep_symbol));
01147 
01148   print(" <a href='$callgraph_href'>[View Callgraph $diff_text]</a><br>");
01149 
01150   print("</center></h4><br>");
01151 
01152   print('<table border=1 cellpadding=2 cellspacing=1 width="90%" '
01153         .'rules=rows bordercolor="#bdc7d8" align=center>' . "\n");
01154   print('<tr bgcolor="#bdc7d8" align=right>');
01155 
01156   foreach ($pc_stats as $stat) {
01157     $desc = stat_description($stat);
01158     if (array_key_exists($stat, $sortable_columns)) {
01159 
01160       $href = "$base_path/?" .
01161         http_build_query(xhprof_array_set($url_params,
01162                                           'sort', $stat));
01163       $header = xhprof_render_link($desc, $href);
01164     } else {
01165       $header = $desc;
01166     }
01167 
01168     if ($stat == "fn")
01169       print("<th align=left><nobr>$header</th>");
01170     else print("<th " . $vwbar . "><nobr>$header</th>");
01171   }
01172   print("</tr>");
01173 
01174   print("<tr bgcolor='#e0e0ff'><td>");
01175   print("<b><i><center>Current Function</center></i></b>");
01176   print("</td></tr>");
01177 
01178   print("<tr>");
01179   // make this a self-reference to facilitate copy-pasting snippets to e-mails
01180   print("<td><a href=''>$rep_symbol</a>");
01181   print_source_link(array('fn' => $rep_symbol));
01182   print("</td>");
01183 
01184   if ($display_calls) {
01185     // Call Count
01186     print_td_num($symbol_info["ct"], $format_cbk["ct"]);
01187     print_td_pct($symbol_info["ct"], $totals["ct"]);
01188   }
01189 
01190   // Inclusive Metrics for current function
01191   foreach ($metrics as $metric) {
01192     print_td_num($symbol_info[$metric], $format_cbk[$metric], ($sort_col == $metric));
01193     print_td_pct($symbol_info[$metric], $totals[$metric], ($sort_col == $metric));
01194   }
01195   print("</tr>");
01196 
01197   print("<tr bgcolor='#ffffff'>");
01198   print("<td style='text-align:right;color:blue'>"
01199         ."Exclusive Metrics $diff_text for Current Function</td>");
01200 
01201   if ($display_calls) {
01202     // Call Count
01203     print("<td $vbar></td>");
01204     print("<td $vbar></td>");
01205   }
01206 
01207   // Exclusive Metrics for current function
01208   foreach ($metrics as $metric) {
01209     print_td_num($symbol_info["excl_" . $metric], $format_cbk["excl_" . $metric],
01210                  ($sort_col == $metric),
01211                  get_tooltip_attributes("Child", $metric));
01212     print_td_pct($symbol_info["excl_" . $metric], $symbol_info[$metric],
01213                  ($sort_col == $metric),
01214                  get_tooltip_attributes("Child", $metric));
01215   }
01216   print("</tr>");
01217 
01218   // list of callers/parent functions
01219   $results = array();
01220   if ($display_calls) {
01221     $base_ct = $symbol_info["ct"];
01222   } else {
01223     $base_ct = 0;
01224   }
01225   foreach ($metrics as $metric) {
01226     $base_info[$metric] = $symbol_info[$metric];
01227   }
01228   foreach ($run_data as $parent_child => $info) {
01229     list($parent, $child) = xhprof_parse_parent_child($parent_child);
01230     if (($child == $rep_symbol) && ($parent)) {
01231       $info_tmp = $info;
01232       $info_tmp["fn"] = $parent;
01233       $results[] = $info_tmp;
01234     }
01235   }
01236   usort($results, 'sort_cbk');
01237 
01238   if (count($results) > 0) {
01239     print_pc_array($url_params, $results, $base_ct, $base_info, true,
01240                    $run1, $run2);
01241   }
01242 
01243   // list of callees/child functions
01244   $results = array();
01245   $base_ct = 0;
01246   foreach ($run_data as $parent_child => $info) {
01247     list($parent, $child) = xhprof_parse_parent_child($parent_child);
01248     if ($parent == $rep_symbol) {
01249       $info_tmp = $info;
01250       $info_tmp["fn"] = $child;
01251       $results[] = $info_tmp;
01252       if ($display_calls) {
01253         $base_ct += $info["ct"];
01254       }
01255     }
01256   }
01257   usort($results, 'sort_cbk');
01258 
01259   if (count($results)) {
01260     print_pc_array($url_params, $results, $base_ct, $base_info, false,
01261                    $run1, $run2);
01262   }
01263 
01264   print("</table>");
01265 
01266   // These will be used for pop-up tips/help.
01267   // Related javascript code is in: xhprof_report.js
01268   print("\n");
01269   print('<script language="javascript">' . "\n");
01270   print("var func_name = '\"" . $rep_symbol . "\"';\n");
01271   print("var total_child_ct  = " . $base_ct . ";\n");
01272   if ($display_calls) {
01273     print("var func_ct   = " . $symbol_info["ct"] . ";\n");
01274   }
01275   print("var func_metrics = new Array();\n");
01276   print("var metrics_col  = new Array();\n");
01277   print("var metrics_desc  = new Array();\n");
01278   if ($diff_mode) {
01279     print("var diff_mode = true;\n");
01280   } else {
01281     print("var diff_mode = false;\n");
01282   }
01283   $column_index = 3; // First three columns are Func Name, Calls, Calls%
01284   foreach ($metrics as $metric) {
01285     print("func_metrics[\"" . $metric . "\"] = " . round($symbol_info[$metric]) . ";\n");
01286     print("metrics_col[\"". $metric . "\"] = " . $column_index . ";\n");
01287     print("metrics_desc[\"". $metric . "\"] = \"" . $possible_metrics[$metric][2] . "\";\n");
01288 
01289     // each metric has two columns..
01290     $column_index += 2;
01291   }
01292   print('</script>');
01293   print("\n");
01294 
01295 }
01296 
01302 function profiler_single_run_report ($url_params,
01303                                      $xhprof_data,
01304                                      $run_desc,
01305                                      $rep_symbol,
01306                                      $sort,
01307                                      $run) {
01308 
01309   init_metrics($xhprof_data, $rep_symbol, $sort, false);
01310 
01311   profiler_report($url_params, $rep_symbol, $sort, $run, $run_desc,
01312                   $xhprof_data);
01313 }
01314 
01315 
01316 
01322 function profiler_diff_report($url_params,
01323                               $xhprof_data1,
01324                               $run1_desc,
01325                               $xhprof_data2,
01326                               $run2_desc,
01327                               $rep_symbol,
01328                               $sort,
01329                               $run1,
01330                               $run2) {
01331 
01332 
01333   // Initialize what metrics we'll display based on data in Run2
01334   init_metrics($xhprof_data2, $rep_symbol, $sort, true);
01335 
01336   profiler_report($url_params,
01337                   $rep_symbol,
01338                   $sort,
01339                   $run1,
01340                   $run1_desc,
01341                   $xhprof_data1,
01342                   $run2,
01343                   $run2_desc,
01344                   $xhprof_data2);
01345 }
01346 
01347 
01382 function displayXHProfReport($xhprof_runs_impl, $url_params, $source,
01383                              $run, $wts, $symbol, $sort, $run1, $run2) {
01384 
01385   if ($run) {                              // specific run to display?
01386 
01387     // run may be a single run or a comma separate list of runs
01388     // that'll be aggregated. If "wts" (a comma separated list
01389     // of integral weights is specified), the runs will be
01390     // aggregated in that ratio.
01391     //
01392     $runs_array = explode(",", $run);
01393 
01394     if (count($runs_array) == 1) {
01395       $xhprof_data = $xhprof_runs_impl->get_run($runs_array[0],
01396                                                 $source,
01397                                                 $description);
01398     } else {
01399       if (!empty($wts)) {
01400         $wts_array  = explode(",", $wts);
01401       } else {
01402         $wts_array = null;
01403       }
01404       $data = xhprof_aggregate_runs($xhprof_runs_impl,
01405                                     $runs_array, $wts_array, $source, false);
01406       $xhprof_data = $data['raw'];
01407       $description = $data['description'];
01408     }
01409 
01410 
01411     profiler_single_run_report($url_params,
01412                                $xhprof_data,
01413                                $description,
01414                                $symbol,
01415                                $sort,
01416                                $run);
01417 
01418   } else if ($run1 && $run2) {                  // diff report for two runs
01419 
01420     $xhprof_data1 = $xhprof_runs_impl->get_run($run1, $source, $description1);
01421     $xhprof_data2 = $xhprof_runs_impl->get_run($run2, $source, $description2);
01422 
01423     profiler_diff_report($url_params,
01424                          $xhprof_data1,
01425                          $description1,
01426                          $xhprof_data2,
01427                          $description2,
01428                          $symbol,
01429                          $sort,
01430                          $run1,
01431                          $run2);
01432 
01433   } else {
01434     echo "No XHProf runs specified in the URL.";
01435     if (method_exists($xhprof_runs_impl, 'list_runs')) {
01436       $xhprof_runs_impl->list_runs();
01437     }
01438   }
01439 }
 All Data Structures Namespaces Files Functions Variables Enumerations