You are here

function xhprof_symbol_report in XHProf 7

Same name and namespace in other branches
  1. 6 xhprof.inc \xhprof_symbol_report()

Generates a report for a single function/symbol.

@author Kannan

1 call to xhprof_symbol_report()
xhprof_profiler_report in ./xhprof.inc
Analyze raw data & generate the profiler report (common for both single run mode and diff mode).

File

./xhprof.inc, line 1080

Code

function xhprof_symbol_report($url_params, $run_data, $symbol_info, $sort, $rep_symbol, $run1, $symbol_info1 = NULL, $run2 = 0, $symbol_info2 = NULL) {
  global $vwbar;
  global $vbar;
  global $totals;
  global $pc_stats;
  global $metrics;
  global $diff_mode;
  global $descriptions;
  global $format_cbk;
  global $sort_col;
  global $display_calls;
  global $base_path;
  $output = '';
  $possible_metrics = xhprof_get_possible_metrics();
  if ($diff_mode) {
    $diff_text = "<b>Diff</b>";
    $regr_impr = "<i style='color:red'>Regression</i>/<i style='color:green'>Improvement</i>";
  }
  else {
    $diff_text = "";
    $regr_impr = "";
  }
  if ($diff_mode) {
    $base_url_params = xhprof_array_unset(xhprof_array_unset($url_params, 'run1'), 'run2');
    $href1 = "{$base_path}?" . http_build_query(xhprof_array_set($base_url_params, 'run', $run1));
    $href2 = "{$base_path}?" . http_build_query(xhprof_array_set($base_url_params, 'run', $run2));
    $output .= "<h3 align=center>{$regr_impr} summary for {$rep_symbol}<br><br></h3>";
    $output .= '<table border=1 cellpadding=2 cellspacing=1 width="30%" ' . 'rules=rows bordercolor="#bdc7d8" align=center>' . "\n";
    $output .= '<tr bgcolor="#bdc7d8" align=right>';
    $output .= "<th align=left>{$rep_symbol}</th>";
    $output .= "<th {$vwbar}><a href=" . $href1 . ">Run #{$run1}</a></th>";
    $output .= "<th {$vwbar}><a href=" . $href2 . ">Run #{$run2}</a></th>";
    $output .= "<th {$vwbar}>Diff</th>";
    $output .= "<th {$vwbar}>Diff%</th>";
    $output .= '</tr>';
    $output .= '<tr>';
    if ($display_calls) {
      $output .= "<td>Number of function xhprof_Calls</td>";
      $output .= xhprof_print_num_cell($symbol_info1["ct"], $format_cbk["ct"]);
      $output .= xhprof_print_num_cell($symbol_info2["ct"], $format_cbk["ct"]);
      $output .= xhprof_print_num_cell($symbol_info2["ct"] - $symbol_info1["ct"], $format_cbk["ct"], TRUE);
      $output .= xhprof_print_pct_cell($symbol_info2["ct"] - $symbol_info1["ct"], $symbol_info1["ct"], TRUE);
      $output .= '</tr>';
    }
    foreach ($metrics as $metric) {
      $m = $metric;

      // Inclusive stat for metric
      $output .= '<tr>';
      $output .= "<td>" . str_replace("<br>", " ", $descriptions[$m]) . "</td>";
      $output .= xhprof_print_num($symbol_info1[$m], $format_cbk[$m]);
      $output .= xhprof_print_num($symbol_info2[$m], $format_cbk[$m]);
      $output .= xhprof_print_num($symbol_info2[$m] - $symbol_info1[$m], $format_cbk[$m], TRUE);
      $output .= xhprof_print_pct($symbol_info2[$m] - $symbol_info1[$m], $symbol_info1[$m], TRUE);
      $output .= '</tr>';

      // AVG (per call) Inclusive stat for metric
      $output .= '<tr>';
      $output .= "<td>" . str_replace("<br>", " ", $descriptions[$m]) . " per call </td>";
      $avg_info1 = 'N/A';
      $avg_info2 = 'N/A';
      if ($symbol_info1['ct'] > 0) {
        $avg_info1 = $symbol_info1[$m] / $symbol_info1['ct'];
      }
      if ($symbol_info2['ct'] > 0) {
        $avg_info2 = $symbol_info2[$m] / $symbol_info2['ct'];
      }
      $output .= xhprof_print_num($avg_info1, $format_cbk[$m]);
      $output .= xhprof_print_num($avg_info2, $format_cbk[$m]);
      $output .= xhprof_print_num($avg_info2 - $avg_info1, $format_cbk[$m], TRUE);
      $output .= xhprof_print_pct($avg_info2 - $avg_info1, $avg_info1, TRUE);
      $output .= '</tr>';

      // Exclusive stat for metric
      $m = "excl_" . $metric;
      $output .= '<tr style="border-bottom: 1px solid black;">';
      $output .= "<td>" . str_replace("<br>", " ", $descriptions[$m]) . "</td>";
      $output .= xhprof_print_num($symbol_info1[$m], $format_cbk[$m]);
      $output .= xhprof_print_num($symbol_info2[$m], $format_cbk[$m]);
      $output .= xhprof_print_num($symbol_info2[$m] - $symbol_info1[$m], $format_cbk[$m], TRUE);
      $output .= xhprof_print_pct($symbol_info2[$m] - $symbol_info1[$m], $symbol_info1[$m], TRUE);
      $output .= '</tr>';
    }
    $output .= '</table>';
  }
  $output .= "<h4>";
  $output .= "Parent/Child {$regr_impr} report for <strong>{$rep_symbol}</strong>";

  // TODO: Maybe include this?

  //$callgraph_href = "$base_path/callgraph.php?" . http_build_query(xhprof_array_set($url_params, 'func', $rep_symbol));

  //$output .= " <a href='$callgraph_href'>[View Callgraph $diff_text]</a>";
  $output .= "</h4>";
  $headers = array();
  $rows = array();

  // Headers.
  foreach ($pc_stats as $stat) {
    $desc = xhprof_stat_description($stat);
    if (array_key_exists($stat, xhprof_sortable_columns($stat))) {
      if ($stat == $sort) {
        $header_desc = l(t($desc), current_path(), array(
          'query' => array(
            'sort' => $stat,
          ),
          t($desc),
        ));
        $headers[] = array(
          'data' => t($header_desc) . theme('tablesort_indicator', array(
            'style' => 'desc',
          )),
        );
      }
      else {
        $header_desc = l(t($desc), current_path(), array(
          'query' => array(
            'sort' => $stat,
          ),
          t($desc),
        ));
        $headers[] = array(
          'data' => t($header_desc),
        );
      }
    }
    else {
      $headers[] = array(
        'data' => t($desc),
      );
    }
  }
  $rows[] = array(
    array(
      'data' => '<strong>Current Function</strong>',
      'colspan' => 11,
    ),
  );

  // Make this a self-reference to facilitate copy-pasting snippets to e-mails.
  $row = array(
    "<a href=''>{$rep_symbol}</a>",
  );
  if ($display_calls) {

    // Call Count.
    $row[] = xhprof_print_num_cell($symbol_info["ct"], $format_cbk["ct"]);
    $row[] = xhprof_print_pct_cell($symbol_info["ct"], $totals["ct"]);
  }

  // Inclusive Metrics for current function.
  foreach ($metrics as $metric) {
    $row[] = xhprof_print_num_cell($symbol_info[$metric], $format_cbk[$metric], $sort_col == $metric);
    $row[] = xhprof_print_pct_cell($symbol_info[$metric], $totals[$metric], $sort_col == $metric);
  }
  $rows[] = $row;
  $row = array(
    "<em>" . t("Exclusive Metrics {$diff_text} for Current Function") . "</em>",
  );
  if ($display_calls) {

    // Call Count
    $row[] = "{$vbar}";
    $row[] = "{$vbar}";
  }

  // Exclusive Metrics for current function
  foreach ($metrics as $metric) {
    $row[] = xhprof_print_num_cell($symbol_info["excl_" . $metric], $format_cbk["excl_" . $metric], $sort_col == $metric, xhprof_get_tooltip_attributes("Child", $metric));
    $row[] = xhprof_print_pct_cell($symbol_info["excl_" . $metric], $symbol_info[$metric], $sort_col == $metric, xhprof_get_tooltip_attributes("Child", $metric));
  }
  $rows[] = $row;

  // list of callers/parent functions
  $results = array();
  $base_ct = $display_calls ? $symbol_info["ct"] : ($base_ct = 0);
  foreach ($metrics as $metric) {
    $base_info[$metric] = $symbol_info[$metric];
  }
  foreach ($run_data as $parent_child => $info) {
    list($parent, $child) = xhprof_parse_parent_child($parent_child);
    if ($child == $rep_symbol && $parent) {
      $info_tmp = $info;
      $info_tmp["fn"] = $parent;
      $results[] = $info_tmp;
    }
  }
  usort($results, 'xhprof_sort_cbk');
  if (count($results) > 0) {
    $pc_row = xhprof_print_pc_array($url_params, $results, $base_ct, $base_info, TRUE, $run1, $run2);
    $rows = array_merge($rows, $pc_row);
  }

  // list of callees/child functions
  $results = array();
  $base_ct = 0;
  foreach ($run_data as $parent_child => $info) {
    list($parent, $child) = xhprof_parse_parent_child($parent_child);
    if ($parent == $rep_symbol) {
      $info_tmp = $info;
      $info_tmp["fn"] = $child;
      $results[] = $info_tmp;
      if ($display_calls) {
        $base_ct += $info["ct"];
      }
    }
  }
  usort($results, 'xhprof_sort_cbk');
  if (count($results)) {
    $pc_row = xhprof_print_pc_array($url_params, $results, $base_ct, $base_info, FALSE, $run1, $run2);
    $rows = array_merge($rows, $pc_row);
  }
  $attributes = array(
    'class' => array(
      'xhprof-table',
    ),
  );
  $output .= theme('table', array(
    'header' => $headers,
    'rows' => $rows,
    'attributes' => $attributes,
  ));

  // TODO: Convert tooltips.
  // These will be used for pop-up tips/help.
  // Related javascript code is in: xhprof_report.js
  $output .= "\n";
  $output .= '<script language="javascript">' . "\n";
  $output .= "var func_name = '\"" . $rep_symbol . "\"';\n";
  $output .= "var total_child_ct  = " . $base_ct . ";\n";
  if ($display_calls) {
    $output .= "var func_ct   = " . $symbol_info["ct"] . ";\n";
  }
  $output .= "var func_metrics = new Array();\n";
  $output .= "var metrics_col  = new Array();\n";
  $output .= "var metrics_desc  = new Array();\n";
  if ($diff_mode) {
    $output .= "var diff_mode = TRUE;\n";
  }
  else {
    $output .= "var diff_mode = FALSE;\n";
  }
  $column_index = 3;

  // First three columns are Func Name, Calls, Calls%
  foreach ($metrics as $metric) {
    $output .= "func_metrics[\"" . $metric . "\"] = " . round($symbol_info[$metric]) . ";\n";
    $output .= "metrics_col[\"" . $metric . "\"] = " . $column_index . ";\n";
    $output .= "metrics_desc[\"" . $metric . "\"] = \"" . $possible_metrics[$metric][2] . "\";\n";

    // each metric has two columns..
    $column_index += 2;
  }
  $output .= '</script>';
  $output .= "\n";
  return $output;
}