View source
<?php
define('XHPROF_STRING_PARAM', 1);
define('XHPROF_UINT_PARAM', 2);
define('XHPROF_FLOAT_PARAM', 3);
define('XHPROF_BOOL_PARAM', 4);
$sort_col = "wt";
$diff_mode = FALSE;
$display_calls = TRUE;
function xhprof_sortable_columns() {
return array(
"fn" => 1,
"ct" => 1,
"wt" => 1,
"excl_wt" => 1,
"ut" => 1,
"excl_ut" => 1,
"st" => 1,
"excl_st" => 1,
"mu" => 1,
"excl_mu" => 1,
"pmu" => 1,
"excl_pmu" => 1,
"cpu" => 1,
"excl_cpu" => 1,
"samples" => 1,
"excl_samples" => 1,
);
}
$descriptions = array(
"fn" => "function xhprof_Name",
"ct" => "Calls",
"Calls%" => "Calls%",
"wt" => "Incl. Wall Time<br>(microsec)",
"IWall%" => "IWall%",
"excl_wt" => "Excl. Wall Time<br>(microsec)",
"EWall%" => "EWall%",
"ut" => "Incl. User<br>(microsecs)",
"IUser%" => "IUser%",
"excl_ut" => "Excl. User<br>(microsec)",
"EUser%" => "EUser%",
"st" => "Incl. Sys <br>(microsec)",
"ISys%" => "ISys%",
"excl_st" => "Excl. Sys <br>(microsec)",
"ESys%" => "ESys%",
"cpu" => "Incl. CPU<br>(microsecs)",
"ICpu%" => "ICpu%",
"excl_cpu" => "Excl. CPU<br>(microsec)",
"ECpu%" => "ECPU%",
"mu" => "Incl.<br>MemUse<br>(bytes)",
"IMUse%" => "IMemUse%",
"excl_mu" => "Excl.<br>MemUse<br>(bytes)",
"EMUse%" => "EMemUse%",
"pmu" => "Incl.<br> PeakMemUse<br>(bytes)",
"IPMUse%" => "IPeakMemUse%",
"excl_pmu" => "Excl.<br>PeakMemUse<br>(bytes)",
"EPMUse%" => "EPeakMemUse%",
"samples" => "Incl. Samples",
"ISamples%" => "ISamples%",
"excl_samples" => "Excl. Samples",
"ESamples%" => "ESamples%",
);
$format_cbk = array(
"fn" => "",
"ct" => "xhprof_count_format",
"Calls%" => "xhprof_percent_format",
"wt" => "number_format",
"IWall%" => "xhprof_percent_format",
"excl_wt" => "number_format",
"EWall%" => "xhprof_percent_format",
"ut" => "number_format",
"IUser%" => "xhprof_percent_format",
"excl_ut" => "number_format",
"EUser%" => "xhprof_percent_format",
"st" => "number_format",
"ISys%" => "xhprof_percent_format",
"excl_st" => "number_format",
"ESys%" => "xhprof_percent_format",
"cpu" => "number_format",
"ICpu%" => "xhprof_percent_format",
"excl_cpu" => "number_format",
"ECpu%" => "xhprof_percent_format",
"mu" => "number_format",
"IMUse%" => "xhprof_percent_format",
"excl_mu" => "number_format",
"EMUse%" => "xhprof_percent_format",
"pmu" => "number_format",
"IPMUse%" => "xhprof_percent_format",
"excl_pmu" => "number_format",
"EPMUse%" => "xhprof_percent_format",
"samples" => "number_format",
"ISamples%" => "xhprof_percent_format",
"excl_samples" => "number_format",
"ESamples%" => "xhprof_percent_format",
);
$diff_descriptions = array(
"fn" => "function xhprof_Name",
"ct" => "Calls Diff",
"Calls%" => "Calls<br>Diff%",
"wt" => "Incl. Wall<br>Diff<br>(microsec)",
"IWall%" => "IWall<br> Diff%",
"excl_wt" => "Excl. Wall<br>Diff<br>(microsec)",
"EWall%" => "EWall<br>Diff%",
"ut" => "Incl. User Diff<br>(microsec)",
"IUser%" => "IUser<br>Diff%",
"excl_ut" => "Excl. User<br>Diff<br>(microsec)",
"EUser%" => "EUser<br>Diff%",
"cpu" => "Incl. CPU Diff<br>(microsec)",
"ICpu%" => "ICpu<br>Diff%",
"excl_cpu" => "Excl. CPU<br>Diff<br>(microsec)",
"ECpu%" => "ECpu<br>Diff%",
"st" => "Incl. Sys Diff<br>(microsec)",
"ISys%" => "ISys<br>Diff%",
"excl_st" => "Excl. Sys Diff<br>(microsec)",
"ESys%" => "ESys<br>Diff%",
"mu" => "Incl.<br>MemUse<br>Diff<br>(bytes)",
"IMUse%" => "IMemUse<br>Diff%",
"excl_mu" => "Excl.<br>MemUse<br>Diff<br>(bytes)",
"EMUse%" => "EMemUse<br>Diff%",
"pmu" => "Incl.<br> PeakMemUse<br>Diff<br>(bytes)",
"IPMUse%" => "IPeakMemUse<br>Diff%",
"excl_pmu" => "Excl.<br>PeakMemUse<br>Diff<br>(bytes)",
"EPMUse%" => "EPeakMemUse<br>Diff%",
"samples" => "Incl. Samples Diff",
"ISamples%" => "ISamples Diff%",
"excl_samples" => "Excl. Samples Diff",
"ESamples%" => "ESamples Diff%",
);
$stats = array();
$pc_stats = array();
$totals = 0;
$totals_1 = 0;
$totals_2 = 0;
$metrics = NULL;
$base_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), "/");
function xhprof_xhprof_include_js_css($ui_dir_url_path = NULL) {
if (empty($ui_dir_url_path)) {
$ui_dir_url_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), "/");
}
echo "<link href='{$ui_dir_url_path}/css/xhprof.css' rel='stylesheet' " . " type='text/css'></link>";
echo "<link href='{$ui_dir_url_path}/jquery/jquery.tooltip.css' " . " rel='stylesheet' type='text/css'></link>";
echo "<link href='{$ui_dir_url_path}/jquery/jquery.autocomplete.css' " . " rel='stylesheet' type='text/css'></link>";
echo "<script src='{$ui_dir_url_path}/jquery/jquery-1.2.6.js'>" . "</script>";
echo "<script src='{$ui_dir_url_path}/jquery/jquery.tooltip.js'>" . "</script>";
echo "<script src='{$ui_dir_url_path}/jquery/jquery.autocomplete.js'>" . "</script>";
echo "<script src='{$ui_dir_url_path}/js/xhprof_report.js'></script>";
}
function xhprof_count_format($num) {
$num = round($num, 3);
if (round($num) == $num) {
return number_format($num);
}
else {
return number_format($num, 3);
}
}
function xhprof_percent_format($s, $precision = 1) {
return sprintf('%.' . $precision . 'f%%', 100 * $s);
}
function xhprof_render_actions($actions) {
$out = array();
if (count($actions)) {
$out[] = '<ul class="xhprof_actions">';
foreach ($actions as $action) {
$out[] = '<li>' . $action . '</li>';
}
$out[] = '</ul>';
}
return implode('', $out);
}
function xhprof_xhprof_render_link($content, $href, $class = '', $id = '', $title = '', $target = '', $onclick = '', $style = '', $access = '', $onmouseover = '', $onmouseout = '', $onmousedown = '') {
if (!$content) {
return '';
}
if ($href) {
$link = '<a href="' . $href . '"';
}
else {
$link = '<span';
}
if ($class) {
$link .= ' class="' . $class . '"';
}
if ($id) {
$link .= ' id="' . $id . '"';
}
if ($title) {
$link .= ' title="' . $title . '"';
}
if ($target) {
$link .= ' target="' . $target . '"';
}
if ($onclick && $href) {
$link .= ' onclick="' . $onclick . '"';
}
if ($style && $href) {
$link .= ' style="' . $style . '"';
}
if ($access && $href) {
$link .= ' accesskey="' . $access . '"';
}
if ($onmouseover) {
$link .= ' onmouseover="' . $onmouseover . '"';
}
if ($onmouseout) {
$link .= ' onmouseout="' . $onmouseout . '"';
}
if ($onmousedown) {
$link .= ' onmousedown="' . $onmousedown . '"';
}
$link .= '>';
$link .= $content;
if ($href) {
$link .= '</a>';
}
else {
$link .= '</span>';
}
return $link;
}
function xhprof_sort_cbk($a, $b) {
global $diff_mode;
$sort_col = isset($_GET['sort']) ? $_GET['sort'] : 'wt';
if ($sort_col == "fn") {
$left = strtoupper($a["fn"]);
$right = strtoupper($b["fn"]);
if ($left == $right) {
return 0;
}
return $left < $right ? -1 : 1;
}
else {
$left = isset($a[$sort_col]) ? $a[$sort_col] : '';
$right = isset($b[$sort_col]) ? $b[$sort_col] : '';
if ($diff_mode) {
$left = abs($left);
$right = abs($right);
}
if ($left == $right) {
return 0;
}
return $left > $right ? -1 : 1;
}
}
function xhprof_init_metrics($xhprof_data, $rep_symbol, $sort, $diff_report = FALSE) {
global $stats;
global $pc_stats;
global $metrics;
global $diff_mode;
global $sort_col;
global $display_calls;
$diff_mode = $diff_report;
if (!empty($sort)) {
if (array_key_exists($sort, xhprof_sortable_columns())) {
$sort_col = $sort;
}
else {
print "Invalid Sort Key {$sort} specified in URL";
}
}
if (!isset($xhprof_data["main()"]["wt"])) {
if ($sort_col == "wt") {
$sort_col = "samples";
}
$display_calls = FALSE;
}
else {
$display_calls = TRUE;
}
if (!empty($rep_symbol)) {
$sort_col = str_replace("excl_", "", $sort_col);
}
if ($display_calls) {
$stats = array(
"fn",
"ct",
"Calls%",
);
}
else {
$stats = array(
"fn",
);
}
$pc_stats = $stats;
$possible_metrics = xhprof_get_possible_metrics($xhprof_data);
foreach ($possible_metrics as $metric => $desc) {
if (isset($xhprof_data["main()"][$metric])) {
$metrics[] = $metric;
$stats[] = $metric;
$stats[] = "I" . $desc[0] . "%";
$stats[] = "excl_" . $metric;
$stats[] = "E" . $desc[0] . "%";
$pc_stats[] = $metric;
$pc_stats[] = "I" . $desc[0] . "%";
}
}
}
function xhprof_stat_description($stat, $desc = FALSE) {
global $diff_mode;
$descriptions = array(
"fn" => "Function Name",
"ct" => "Calls",
"Calls%" => "Calls%",
"wt" => "Incl. Wall Time (microsec)",
"IWall%" => "IWall%",
"excl_wt" => "Excl. Wall Time (microsec)",
"EWall%" => "EWall%",
"ut" => "Incl. User (microsecs)",
"IUser%" => "IUser%",
"excl_ut" => "Excl. User (microsec)",
"EUser%" => "EUser%",
"st" => "Incl. Sys (microsec)",
"ISys%" => "ISys%",
"excl_st" => "Excl. Sys (microsec)",
"ESys%" => "ESys%",
"cpu" => "Incl. CPU (microsecs)",
"ICpu%" => "ICpu%",
"excl_cpu" => "Excl. CPU (microsec)",
"ECpu%" => "ECPU%",
"mu" => "Incl. MemUse (bytes)",
"IMUse%" => "IMemUse%",
"excl_mu" => "Excl. MemUse (bytes)",
"EMUse%" => "EMemUse%",
"pmu" => "Incl. PeakMemUse (bytes)",
"IPMUse%" => "IPeakMemUse%",
"excl_pmu" => "Excl. PeakMemUse (bytes)",
"EPMUse%" => "EPeakMemUse%",
"samples" => "Incl. Samples",
"ISamples%" => "ISamples%",
"excl_samples" => "Excl. Samples",
"ESamples%" => "ESamples%",
);
$diff_descriptions = array(
"fn" => "Function Name",
"ct" => "Calls Diff",
"Calls%" => "Calls Diff%",
"wt" => "Incl. Wall Diff (microsec)",
"IWall%" => "IWall Diff%",
"excl_wt" => "Excl. Wall Diff (microsec)",
"EWall%" => "EWall Diff%",
"ut" => "Incl. User Diff (microsec)",
"IUser%" => "IUser Diff%",
"excl_ut" => "Excl. User Diff (microsec)",
"EUser%" => "EUser Diff%",
"cpu" => "Incl. CPU Diff (microsec)",
"ICpu%" => "ICpu Diff%",
"excl_cpu" => "Excl. CPU Diff (microsec)",
"ECpu%" => "ECpu Diff%",
"st" => "Incl. Sys Diff (microsec)",
"ISys%" => "ISys Diff%",
"excl_st" => "Excl. Sys Diff (microsec)",
"ESys%" => "ESys Diff%",
"mu" => "Incl. MemUse Diff (bytes)",
"IMUse%" => "IMemUse Diff%",
"excl_mu" => "Excl. MemUse Diff (bytes)",
"EMUse%" => "EMemUse Diff%",
"pmu" => "Incl. PeakMemUse Diff (bytes)",
"IPMUse%" => "IPeakMemUse Diff%",
"excl_pmu" => "Excl. PeakMemUse Diff (bytes)",
"EPMUse%" => "EPeakMemUse Diff%",
"samples" => "Incl. Samples Diff",
"ISamples%" => "ISamples Diff%",
"excl_samples" => "Excl. Samples Diff",
"ESamples%" => "ESamples Diff%",
);
if ($diff_mode) {
if ($desc) {
$diff_descriptions = array_flip($diff_descriptions);
}
return $diff_descriptions[$stat];
}
else {
if ($desc) {
$descriptions = array_flip($descriptions);
}
return $descriptions[$stat];
}
}
function xhprof_profiler_report($url_params, $rep_symbol, $sort, $run1, $run1_desc, $run1_data, $run2 = 0, $run2_desc = "", $run2_data = array()) {
global $totals;
global $totals_1;
global $totals_2;
global $stats;
global $pc_stats;
global $diff_mode;
global $base_path;
$output = '';
if (!empty($rep_symbol)) {
$run1_data = xhprof_trim_run($run1_data, array(
$rep_symbol,
));
if ($diff_mode) {
$run2_data = xhprof_trim_run($run2_data, array(
$rep_symbol,
));
}
}
if ($diff_mode) {
$run_delta = xhprof_compute_diff($run1_data, $run2_data);
$symbol_tab = xhprof_compute_flat_info($run_delta, $totals);
$symbol_tab1 = xhprof_compute_flat_info($run1_data, $totals_1);
$symbol_tab2 = xhprof_compute_flat_info($run2_data, $totals_2);
}
else {
$symbol_tab = xhprof_compute_flat_info($run1_data, $totals);
}
$run1_txt = sprintf("<b>Run #%s:</b> %s", $run1, $run1_desc);
if ($diff_mode) {
$diff_text = "Diff";
$run1_link = l('View Run #' . $run1, xhprof_path_for_run($run1));
$run2_txt = sprintf("<b>Run #%s:</b> %s", $run2, $run2_desc);
$run2_link = l('View Run #' . $run2, xhprof_path_for_run($run2));
}
else {
$diff_text = "Run";
}
$links = array();
$links[] = l("View Top Level {$diff_text} Report", xhprof_path_for_run($run1, $run2));
if ($diff_mode) {
$inverted_params = $url_params;
$inverted_params['run1'] = $url_params['run2'];
$inverted_params['run2'] = $url_params['run1'];
$links[] = $run1_link;
$links[] = $run2_link;
$links[] = l('Invert ' . $diff_text . ' Report', xhprof_path_for_run($run2, $run1));
}
$output .= xhprof_render_actions($links);
$output .= '<dl class=xhprof_report_info>' . ' <dt>' . $diff_text . ' Report</dt>' . ' <dd>' . ($diff_mode ? $run1_txt . '<br><b>vs.</b><br>' . $run2_txt : $run1_txt) . ' </dd>' . '</dl>';
if (!empty($rep_symbol)) {
if (!isset($symbol_tab[$rep_symbol])) {
drupal_set_message(t("Symbol <strong>{$rep_symbol}</strong> not found in XHProf run"));
return $output;
}
if ($diff_mode) {
$info1 = isset($symbol_tab1[$rep_symbol]) ? $symbol_tab1[$rep_symbol] : NULL;
$info2 = isset($symbol_tab2[$rep_symbol]) ? $symbol_tab2[$rep_symbol] : NULL;
$output .= xhprof_symbol_report($url_params, $run_delta, $symbol_tab[$rep_symbol], $sort, $rep_symbol, $run1, $info1, $run2, $info2);
}
else {
$output .= xhprof_symbol_report($url_params, $run1_data, $symbol_tab[$rep_symbol], $sort, $rep_symbol, $run1);
}
}
else {
$output .= xhprof_full_report($url_params, $symbol_tab, $sort, $run1, $run2);
}
return $output;
}
function xhprof_get_print_class($num, $bold) {
global $vbar;
global $vbbar;
global $vrbar;
global $vgbar;
global $diff_mode;
if ($bold) {
if ($diff_mode) {
if ($num <= 0) {
$class = 'vgbar';
}
else {
$class = 'vrbar';
}
}
else {
$class = 'vbbar';
}
}
else {
$class = 'vbar';
}
return $class;
}
function xhprof_print_num($num, $fmt_func = NULL, $bold = FALSE, $attributes = NULL) {
$class = xhprof_get_print_class($num, $bold);
if (!empty($fmt_func)) {
$num = call_user_func($fmt_func, $num);
}
$num = number_format($num);
return "<span class='{$class}'>{$num}</span>\n";
}
function xhprof_print_pct($numer, $denom, $bold = FALSE, $attributes = NULL) {
global $vbar;
global $vbbar;
global $diff_mode;
$class = xhprof_get_print_class($numer, $bold);
if ($denom == 0) {
$pct = "N/A%";
}
else {
$pct = xhprof_percent_format($numer / abs($denom));
}
return "<span class='{$class}'>{$pct}</span>";
}
function xhprof_print_function_info($url_params, $info, $sort, $run1, $run2) {
global $totals;
global $sort_col;
global $metrics;
global $format_cbk;
global $display_calls;
global $base_path;
$output = '';
$href = "{$base_path}/?" . http_build_query(xhprof_array_set($url_params, 'symbol', $info["fn"]));
if ($display_calls) {
$output .= xhprof_print_num_cell($info["ct"], $format_cbk["ct"], $sort_col == "ct");
$output .= xhprof_print_pct_cell($info["ct"], $totals["ct"], $sort_col == "ct");
}
foreach ($metrics as $metric) {
$output .= xhprof_print_num_cell($info[$metric], $format_cbk[$metric], $sort_col == $metric);
$output .= xhprof_print_pct_cell($info[$metric], $totals[$metric], $sort_col == $metric);
$output .= xhprof_print_num_cell($info["excl_" . $metric], $format_cbk["excl_" . $metric], $sort_col == "excl_" . $metric);
$output .= xhprof_print_pct_cell($info["excl_" . $metric], $totals[$metric], $sort_col == "excl_" . $metric);
}
return $output;
}
function xhprof_print_flat_data($url_params, $title, $flat_data, $sort, $run1, $run2, $limit) {
global $stats;
global $pc_stats;
global $totals;
global $vwbar;
global $base_path;
$output = '';
$attributes = array(
'id' => 'xhprof-run-table',
);
$header = array();
foreach ($stats as $stat) {
$desc = xhprof_stat_description($stat);
if (array_key_exists($stat, xhprof_sortable_columns($stat))) {
if (isset($_GET['sort']) && $stat == $_GET['sort']) {
$header_desc = l(t($desc), current_path(), array(
'query' => array(
'sort' => $stat,
),
t($desc),
));
$header[] = 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),
));
$header[] = array(
'data' => t($header_desc),
);
}
}
else {
$header[] = array(
'data' => t($desc),
);
}
}
$rows = array();
$trail = menu_get_active_trail();
foreach ($flat_data as $data) {
$row = array(
array(
'data' => l($data["fn"], $trail[1]["href"] . '/' . $data["fn"]),
),
array(
'data' => $data['ct'],
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_pct($data['ct'], $totals['ct']),
'class' => 'xhprof_percent',
),
array(
'data' => $data['wt'],
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_pct($data['wt'], $totals['wt']),
),
array(
'data' => $data['excl_wt'],
'class' => 'xhprof_percent',
),
array(
'data' => xhprof_print_pct($data['excl_wt'], $totals['wt']),
'class' => 'xhprof_micro',
),
array(
'data' => $data['cpu'],
'class' => 'xhprof_percent',
),
array(
'data' => xhprof_print_pct($data['cpu'], $totals['cpu']),
'class' => 'xhprof_percent',
),
array(
'data' => $data['excl_cpu'],
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_pct($data['excl_cpu'], $totals['cpu']),
'class' => 'xhprof_percent',
),
array(
'data' => $data['mu'],
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_pct($data['mu'], $totals['mu']),
'class' => 'xhprof_percent',
),
array(
'data' => $data['excl_mu'],
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_pct($data['excl_mu'], $totals['mu']),
'xhprof_percent',
),
array(
'data' => $data['pmu'],
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_pct($data['pmu'], $totals['pmu']),
'xhprof_percent',
),
array(
'data' => $data['excl_pmu'],
'xhprof_micro',
),
array(
'data' => xhprof_print_pct($data['excl_pmu'], $totals['pmu']),
'class' => 'xhprof_percent',
),
);
$rows[] = $row;
}
$size = count($flat_data);
if (!$limit) {
$limit = $size;
$display_link = "";
}
else {
$display_link = xhprof_xhprof_render_link(" [ <b class=bubble>display all </b>]", "{$base_path}/?" . http_build_query(xhprof_array_set($url_params, 'all', 1)));
}
$output .= "<h3 align=center>{$title} {$display_link}</h3><br>";
$output .= theme('table', array(
'header' => $header,
'rows' => $rows,
'attributes' => $attributes,
));
return $output;
}
function xhprof_full_report($url_params, $symbol_tab, $sort, $run1, $run2) {
global $vwbar;
global $vbar;
global $totals;
global $totals_1;
global $totals_2;
global $metrics;
global $diff_mode;
global $descriptions;
global $sort_col;
global $format_cbk;
global $display_calls;
global $base_path;
global $stats;
$possible_metrics = xhprof_get_possible_metrics();
$output = '';
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><center>Overall Diff Summary</center></h3>";
$headers = array();
$headers[] = "";
$headers[] = xhprof_xhprof_render_link("Run #{$run1}", $href1);
$headers[] = xhprof_xhprof_render_link("Run #{$run2}", $href2);
$headers[] = 'Diff';
$headers[] = 'Diff%';
$rows = array();
if ($display_calls) {
$row = array(
array(
'data' => 'Number of function xhprof_Calls',
),
array(
'data' => xhprof_print_num($totals_1["ct"], $format_cbk["ct"]),
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_num($totals_2["ct"], $format_cbk["ct"]),
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_num($totals_2["ct"] - $totals_1["ct"], $format_cbk["ct"], TRUE),
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_pct($totals_2["ct"] - $totals_1["ct"], $totals_1["ct"], TRUE),
'class' => 'xhprof_percent',
),
);
$rows[] = $row;
}
foreach ($metrics as $m) {
$desc = xhprof_stat_description($m, $desc = FALSE);
$row = array(
array(
'data' => str_replace("<br>", " ", $desc),
),
array(
'data' => xhprof_print_num($totals_1[$m], $format_cbk[$m]),
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_num($totals_2[$m], $format_cbk[$m]),
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_num($totals_2[$m] - $totals_1[$m], $format_cbk[$m], TRUE),
'class' => 'xhprof_micro',
),
array(
'data' => xhprof_print_pct($totals_2[$m] - $totals_1[$m], $totals_1[$m], TRUE),
'class' => 'xhprof_percent',
),
);
$rows[] = $row;
}
$attributes = array(
'class' => array(
'xhprof-table',
'xhprof-summary-table',
),
);
$output .= theme('table', array(
'header' => $headers,
'rows' => $rows,
'attributes' => $attributes,
));
$callgraph_report_title = '[View Regressions/Improvements using Callgraph Diff]';
}
else {
$vars = array(
'totals' => $totals,
'possible_metrics' => $possible_metrics,
'metrics' => $metrics,
'display_calls' => $display_calls,
);
$output .= theme('xhprof_overall_summary', $vars);
}
$output .= "<center><br><h3>";
$output .= "</h3></center>";
$flat_data = array();
foreach ($symbol_tab as $symbol => $info) {
$tmp = $info;
$tmp["fn"] = $symbol;
$flat_data[] = $tmp;
}
usort($flat_data, 'xhprof_sort_cbk');
$output .= "<br>";
if (!empty($url_params['all'])) {
$all = TRUE;
$limit = 0;
}
else {
$all = FALSE;
$limit = 100;
}
$desc = str_replace("<br>", " ", $descriptions[$sort_col]);
if ($diff_mode) {
if ($all) {
$title = "Total Diff Report: '\n .'Sorted by absolute value of regression/improvement in {$desc}";
}
else {
$title = "Top 100 <em style='color:red'>Regressions</em>/" . "<em style='color:green'>Improvements</em>: " . "Sorted by {$desc} Diff";
}
}
else {
if ($all) {
$title = "Sorted by {$desc}";
}
else {
$title = "Displaying top {$limit} functions: Sorted by {$desc}";
}
}
$vars = array(
'stats' => $stats,
'totals' => $totals,
'url_params' => $url_params,
'title' => $title,
'flat_data' => $flat_data,
'limit' => $limit,
'run1' => $run1,
'run2' => $run2,
);
$output .= theme('xhprof_run_table', $vars);
return $output;
}
function xhprof_get_tooltip_attributes($type, $metric) {
return "type='{$type}' metric='{$metric}'";
}
function xhprof_pc_info($info, $base_ct, $base_info, $parent) {
global $sort_col;
global $metrics;
global $format_cbk;
global $display_calls;
$type = $parent ? "Parent" : "Child";
if ($display_calls) {
$mouseoverct = xhprof_get_tooltip_attributes($type, "ct");
$row = array(
xhprof_print_num_cell($info["ct"], $format_cbk["ct"], $sort_col == "ct", $mouseoverct),
);
$row[] = xhprof_print_pct_cell($info["ct"], $base_ct, $sort_col == "ct", $mouseoverct);
}
foreach ($metrics as $metric) {
$row[] = xhprof_print_num_cell($info[$metric], $format_cbk[$metric], $sort_col == $metric, xhprof_get_tooltip_attributes($type, $metric));
$row[] = xhprof_print_pct_cell($info[$metric], $base_info[$metric], $sort_col == $metric, xhprof_get_tooltip_attributes($type, $metric));
}
return $row;
}
function xhprof_print_pc_array($url_params, $results, $base_ct, $base_info, $parent, $run1, $run2) {
global $base_path;
$rows = array();
$title = $parent ? 'Parent function' : 'Child function';
if (count($results) > 1) {
$title = '<strong>' . $title . 's</strong>';
}
$rows[] = array(
array(
'data' => $title,
'colspan' => 11,
),
);
usort($results, 'xhprof_sort_cbk');
foreach ($results as $info) {
$row = array();
$row[] = l($info["fn"], xhprof_path_for_symbol($info["fn"], $run1, $run2));
$row = array_merge($row, xhprof_pc_info($info, $base_ct, $base_info, $parent));
$rows[] = $row;
}
return $rows;
}
function xhprof_print_symbol_summary($symbol_info, $stat, $base) {
$val = $symbol_info[$stat];
$desc = str_replace("<br>", " ", xhprof_stat_description($stat));
$output .= "{$desc}: </td>";
$output .= number_format($val);
$output .= " (" . pct($val, $base) . "% of overall)";
if (substr($stat, 0, 4) == "excl") {
$func_base = $symbol_info[str_replace("excl_", "", $stat)];
$output .= " (" . pct($val, $func_base) . "% of this function)";
}
$output .= "<br>";
return $output;
}
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;
$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>';
$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>';
$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>";
$output .= "</h4>";
$headers = array();
$rows = array();
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,
),
);
$row = array(
"<a href=''>{$rep_symbol}</a>",
);
if ($display_calls) {
$row[] = xhprof_print_num_cell($symbol_info["ct"], $format_cbk["ct"]);
$row[] = xhprof_print_pct_cell($symbol_info["ct"], $totals["ct"]);
}
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) {
$row[] = "{$vbar}";
$row[] = "{$vbar}";
}
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;
$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);
}
$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,
));
$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;
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";
$column_index += 2;
}
$output .= '</script>';
$output .= "\n";
return $output;
}
function xhprof_displayXHProfReport($xhprof_runs_impl, $options) {
extract($options);
if ($run) {
$runs_array = explode(",", $run);
if (isset($_GET['order'])) {
$sort = xhprof_stat_description($_GET['order'], TRUE);
}
if (count($runs_array) == 1) {
$xhprof_data = $xhprof_runs_impl
->get_run($runs_array[0], $source, $description, $sort);
}
else {
if (!empty($wts)) {
$wts_array = explode(",", $wts);
}
else {
$wts_array = NULL;
}
$data = xhprof_aggregate_runs($xhprof_runs_impl, $runs_array, $wts_array, $source, FALSE);
$xhprof_data = $data['raw'];
$description = $data['description'];
}
$output .= xhprof_profiler_single_run_report($url_params, $xhprof_data, $description, $symbol, $sort, $run);
}
elseif ($run1 && $run2) {
$xhprof_data1 = $xhprof_runs_impl
->get_run($run1, $source, $description1);
$xhprof_data2 = $xhprof_runs_impl
->get_run($run2, $source, $description2);
$output .= xhprof_profiler_diff_report($url_params, $xhprof_data1, $description1, $xhprof_data2, $description2, $symbol, $sort, $run1, $run2);
}
else {
$output .= "No XHProf runs specified in the URL.";
}
return $output;
}
function xhprof_array_set($arr, $k, $v) {
$arr[$k] = $v;
return $arr;
}
function xhprof_array_unset($arr, $k) {
unset($arr[$k]);
return $arr;
}
function xhprof_trim_run($raw_data, $functions_to_keep) {
$function_map = array_fill_keys($functions_to_keep, 1);
$function_map['main()'] = 1;
$new_raw_data = array();
foreach ($raw_data as $parent_child => $info) {
list($parent, $child) = xhprof_parse_parent_child($parent_child);
if (isset($function_map[$parent]) || isset($function_map[$child])) {
$new_raw_data[$parent_child] = $info;
}
}
return $new_raw_data;
}
function xhprof_compute_diff($xhprof_data1, $xhprof_data2) {
global $display_calls;
$metrics = xhprof_get_metrics($xhprof_data2);
$xhprof_delta = $xhprof_data2;
foreach ($xhprof_data1 as $parent_child => $info) {
if (!isset($xhprof_delta[$parent_child])) {
if ($display_calls) {
$xhprof_delta[$parent_child] = array(
"ct" => 0,
);
}
else {
$xhprof_delta[$parent_child] = array();
}
foreach ($metrics as $metric) {
$xhprof_delta[$parent_child][$metric] = 0;
}
}
if ($display_calls) {
$xhprof_delta[$parent_child]["ct"] -= $info["ct"];
}
foreach ($metrics as $metric) {
$xhprof_delta[$parent_child][$metric] -= $info[$metric];
}
}
return $xhprof_delta;
}
function xhprof_get_metrics($xhprof_data) {
$possible_metrics = xhprof_get_possible_metrics();
$metrics = array();
foreach ($possible_metrics as $metric => $desc) {
if (isset($xhprof_data["main()"][$metric])) {
$metrics[] = $metric;
}
}
return $metrics;
}
function xhprof_parse_parent_child($parent_child) {
$ret = explode("==>", $parent_child);
if (isset($ret[1])) {
return $ret;
}
return array(
NULL,
$ret[0],
);
}
function xhprof_compute_flat_info($raw_data, &$overall_totals) {
$metrics = xhprof_get_metrics($raw_data);
$overall_totals = array(
"ct" => 0,
"wt" => 0,
"ut" => 0,
"st" => 0,
"cpu" => 0,
"mu" => 0,
"pmu" => 0,
"samples" => 0,
);
$symbol_tab = xhprof_compute_inclusive_times($raw_data);
foreach ($metrics as $metric) {
$overall_totals[$metric] = $symbol_tab["main()"][$metric];
}
foreach ($symbol_tab as $symbol => $info) {
foreach ($metrics as $metric) {
$symbol_tab[$symbol]["excl_" . $metric] = $symbol_tab[$symbol][$metric];
}
$overall_totals["ct"] += $info["ct"];
}
foreach ((array) $raw_data as $parent_child => $info) {
list($parent, $child) = xhprof_parse_parent_child($parent_child);
if ($parent) {
foreach ($metrics as $metric) {
if (isset($symbol_tab[$parent])) {
$symbol_tab[$parent]["excl_" . $metric] -= $info[$metric];
}
}
}
}
return $symbol_tab;
}
function xhprof_compute_inclusive_times($raw_data) {
$metrics = xhprof_get_metrics($raw_data);
$symbol_tab = array();
foreach ((array) $raw_data as $parent_child => $info) {
list($parent, $child) = xhprof_parse_parent_child($parent_child);
if ($parent == $child) {
watchdog("Error in Raw Data: parent & child are both: %parent", array(
'%parent' => $parent,
));
return;
}
if (!isset($symbol_tab[$child])) {
$symbol_tab[$child] = array(
"ct" => $info["ct"],
);
foreach ($metrics as $metric) {
$symbol_tab[$child][$metric] = $info[$metric];
}
}
else {
$symbol_tab[$child]["ct"] += $info["ct"];
foreach ($metrics as $metric) {
$symbol_tab[$child][$metric] += $info[$metric];
}
}
}
return $symbol_tab;
}
function xhprof_get_possible_metrics() {
$possible_metrics = array(
"wt" => array(
"Wall",
"microsecs",
"walltime",
),
"ut" => array(
"User",
"microsecs",
"user cpu time",
),
"st" => array(
"Sys",
"microsecs",
"system cpu time",
),
"cpu" => array(
"Cpu",
"microsecs",
"cpu time",
),
"mu" => array(
"MUse",
"bytes",
"memory usage",
),
"pmu" => array(
"PMUse",
"bytes",
"peak memory usage",
),
"samples" => array(
"Samples",
"samples",
"cpu time",
),
);
return $possible_metrics;
}