[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 // Copyright (c) 2009 Facebook 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 // 18 // This file contains various XHProf library (utility) functions. 19 // Do not add any display specific code here. 20 // 21 22 function xhprof_error($message) { 23 error_log($message); 24 } 25 26 /* 27 * The list of possible metrics collected as part of XHProf that 28 * require inclusive/exclusive handling while reporting. 29 * 30 * @author Kannan 31 */ 32 function xhprof_get_possible_metrics() { 33 static $possible_metrics = 34 array("wt" => array("Wall", "microsecs", "walltime" ), 35 "ut" => array("User", "microsecs", "user cpu time" ), 36 "st" => array("Sys", "microsecs", "system cpu time"), 37 "cpu" => array("Cpu", "microsecs", "cpu time"), 38 "mu" => array("MUse", "bytes", "memory usage"), 39 "pmu" => array("PMUse", "bytes", "peak memory usage"), 40 "samples" => array("Samples", "samples", "cpu time")); 41 return $possible_metrics; 42 } 43 44 /* 45 * Get the list of metrics present in $xhprof_data as an array. 46 * 47 * @author Kannan 48 */ 49 function xhprof_get_metrics($xhprof_data) { 50 51 // get list of valid metrics 52 $possible_metrics = xhprof_get_possible_metrics(); 53 54 // return those that are present in the raw data. 55 // We'll just look at the root of the subtree for this. 56 $metrics = array(); 57 foreach ($possible_metrics as $metric => $desc) { 58 if (isset($xhprof_data["main()"][$metric])) { 59 $metrics[] = $metric; 60 } 61 } 62 63 return $metrics; 64 } 65 66 /** 67 * Takes a parent/child function name encoded as 68 * "a==>b" and returns array("a", "b"). 69 * 70 * @author Kannan 71 */ 72 function xhprof_parse_parent_child($parent_child) { 73 $ret = explode("==>", $parent_child); 74 75 // Return if both parent and child are set 76 if (isset($ret[1])) { 77 return $ret; 78 } 79 80 return array(null, $ret[0]); 81 } 82 83 /** 84 * Given parent & child function name, composes the key 85 * in the format present in the raw data. 86 * 87 * @author Kannan 88 */ 89 function xhprof_build_parent_child_key($parent, $child) { 90 if ($parent) { 91 return $parent . "==>" . $child; 92 } else { 93 return $child; 94 } 95 } 96 97 98 /** 99 * Checks if XHProf raw data appears to be valid and not corrupted. 100 * 101 * @param int $run_id Run id of run to be pruned. 102 * [Used only for reporting errors.] 103 * @param array $raw_data XHProf raw data to be pruned 104 * & validated. 105 * 106 * @return bool true on success, false on failure 107 * 108 * @author Kannan 109 */ 110 function xhprof_valid_run($run_id, $raw_data) { 111 112 $main_info = $raw_data["main()"]; 113 if (empty($main_info)) { 114 xhprof_error("XHProf: main() missing in raw data for Run ID: $run_id"); 115 return false; 116 } 117 118 // raw data should contain either wall time or samples information... 119 if (isset($main_info["wt"])) { 120 $metric = "wt"; 121 } else if (isset($main_info["samples"])) { 122 $metric = "samples"; 123 } else { 124 xhprof_error("XHProf: Wall Time information missing from Run ID: $run_id"); 125 return false; 126 } 127 128 foreach ($raw_data as $info) { 129 $val = $info[$metric]; 130 131 // basic sanity checks... 132 if ($val < 0) { 133 xhprof_error("XHProf: $metric should not be negative: Run ID $run_id" 134 . serialize($info)); 135 return false; 136 } 137 if ($val > (86400000000)) { 138 xhprof_error("XHProf: $metric > 1 day found in Run ID: $run_id " 139 . serialize($info)); 140 return false; 141 } 142 } 143 return true; 144 } 145 146 147 /** 148 * Return a trimmed version of the XHProf raw data. Note that the raw 149 * data contains one entry for each unique parent/child function 150 * combination.The trimmed version of raw data will only contain 151 * entries where either the parent or child function is in the list 152 * of $functions_to_keep. 153 * 154 * Note: Function main() is also always kept so that overall totals 155 * can still be obtained from the trimmed version. 156 * 157 * @param array XHProf raw data 158 * @param array array of function names 159 * 160 * @return array Trimmed XHProf Report 161 * 162 * @author Kannan 163 */ 164 function xhprof_trim_run($raw_data, $functions_to_keep) { 165 166 // convert list of functions to a hash with function as the key 167 $function_map = array_fill_keys($functions_to_keep, 1); 168 169 // always keep main() as well so that overall totals can still 170 // be computed if need be. 171 $function_map['main()'] = 1; 172 173 $new_raw_data = array(); 174 foreach ($raw_data as $parent_child => $info) { 175 list($parent, $child) = xhprof_parse_parent_child($parent_child); 176 177 if (isset($function_map[$parent]) || isset($function_map[$child])) { 178 $new_raw_data[$parent_child] = $info; 179 } 180 } 181 182 return $new_raw_data; 183 } 184 185 /** 186 * Takes raw XHProf data that was aggregated over "$num_runs" number 187 * of runs averages/nomalizes the data. Essentially the various metrics 188 * collected are divided by $num_runs. 189 * 190 * @author Kannan 191 */ 192 function xhprof_normalize_metrics($raw_data, $num_runs) { 193 194 if (empty($raw_data) || ($num_runs == 0)) { 195 return $raw_data; 196 } 197 198 $raw_data_total = array(); 199 200 if (isset($raw_data["==>main()"]) && isset($raw_data["main()"])) { 201 xhprof_error("XHProf Error: both ==>main() and main() set in raw data..."); 202 } 203 204 foreach ($raw_data as $parent_child => $info) { 205 foreach ($info as $metric => $value) { 206 $raw_data_total[$parent_child][$metric] = ($value / $num_runs); 207 } 208 } 209 210 return $raw_data_total; 211 } 212 213 214 /** 215 * Get raw data corresponding to specified array of runs 216 * aggregated by certain weightage. 217 * 218 * Suppose you have run:5 corresponding to page1.php, 219 * run:6 corresponding to page2.php, 220 * and run:7 corresponding to page3.php 221 * 222 * and you want to accumulate these runs in a 2:4:1 ratio. You 223 * can do so by calling: 224 * 225 * xhprof_aggregate_runs(array(5, 6, 7), array(2, 4, 1)); 226 * 227 * The above will return raw data for the runs aggregated 228 * in 2:4:1 ratio. 229 * 230 * @param object $xhprof_runs_impl An object that implements 231 * the iXHProfRuns interface 232 * @param array $runs run ids of the XHProf runs.. 233 * @param array $wts integral (ideally) weights for $runs 234 * @param string $source source to fetch raw data for run from 235 * @param bool $use_script_name If true, a fake edge from main() to 236 * to __script::<scriptname> is introduced 237 * in the raw data so that after aggregations 238 * the script name is still preserved. 239 * 240 * @return array Return aggregated raw data 241 * 242 * @author Kannan 243 */ 244 function xhprof_aggregate_runs($xhprof_runs_impl, $runs, 245 $wts, $source="phprof", 246 $use_script_name=false) { 247 248 $raw_data_total = null; 249 $raw_data = null; 250 $metrics = array(); 251 252 $run_count = count($runs); 253 $wts_count = count($wts); 254 255 if (($run_count == 0) || 256 (($wts_count > 0) && ($run_count != $wts_count))) { 257 return array('description' => 'Invalid input..', 258 'raw' => null); 259 } 260 261 $bad_runs = array(); 262 foreach($runs as $idx => $run_id) { 263 264 $raw_data = $xhprof_runs_impl->get_run($run_id, $source, '?'); 265 266 // use the first run to derive what metrics to aggregate on. 267 if ($idx == 0) { 268 foreach ($raw_data["main()"] as $metric => $val) { 269 if ($metric != "pmu") { 270 // for now, just to keep data size small, skip "peak" memory usage 271 // data while aggregating. 272 // The "regular" memory usage data will still be tracked. 273 if (isset($val)) { 274 $metrics[] = $metric; 275 } 276 } 277 } 278 } 279 280 if (!xhprof_valid_run($run_id, $raw_data)) { 281 $bad_runs[] = $run_id; 282 continue; 283 } 284 285 if ($use_script_name) { 286 $page = '?'; 287 288 // create a fake function '__script::$page', and have and edge from 289 // main() to '__script::$page'. We will also need edges to transfer 290 // all edges originating from main() to now originate from 291 // '__script::$page' to all function called from main(). 292 // 293 // We also weight main() ever so slightly higher so that 294 // it shows up above the new entry in reports sorted by 295 // inclusive metrics or call counts. 296 if ($page) { 297 foreach($raw_data["main()"] as $metric => $val) { 298 $fake_edge[$metric] = $val; 299 $new_main[$metric] = $val + 0.00001; 300 } 301 $raw_data["main()"] = $new_main; 302 $raw_data[xhprof_build_parent_child_key("main()", 303 "__script::$page")] 304 = $fake_edge; 305 } else { 306 $use_script_name = false; 307 } 308 } 309 310 // if no weights specified, use 1 as the default weightage.. 311 $wt = ($wts_count == 0) ? 1 : $wts[$idx]; 312 313 // aggregate $raw_data into $raw_data_total with appropriate weight ($wt) 314 foreach ($raw_data as $parent_child => $info) { 315 if ($use_script_name) { 316 // if this is an old edge originating from main(), it now 317 // needs to be from '__script::$page' 318 if (substr($parent_child, 0, 9) == "main()==>") { 319 $child =substr($parent_child, 9); 320 // ignore the newly added edge from main() 321 if (substr($child, 0, 10) != "__script::") { 322 $parent_child = xhprof_build_parent_child_key("__script::$page", 323 $child); 324 } 325 } 326 } 327 328 if (!isset($raw_data_total[$parent_child])) { 329 foreach ($metrics as $metric) { 330 $raw_data_total[$parent_child][$metric] = ($wt * $info[$metric]); 331 } 332 } else { 333 foreach ($metrics as $metric) { 334 $raw_data_total[$parent_child][$metric] += ($wt * $info[$metric]); 335 } 336 } 337 } 338 } 339 340 $runs_string = implode(",", $runs); 341 342 if (isset($wts)) { 343 $wts_string = "in the ratio (" . implode(":", $wts) . ")"; 344 $normalization_count = array_sum($wts); 345 } else { 346 $wts_string = ""; 347 $normalization_count = $run_count; 348 } 349 350 $run_count = $run_count - count($bad_runs); 351 352 $data['description'] = "Aggregated Report for $run_count runs: ". 353 "$runs_string $wts_string\n"; 354 $data['raw'] = xhprof_normalize_metrics($raw_data_total, 355 $normalization_count); 356 $data['bad_runs'] = $bad_runs; 357 358 return $data; 359 } 360 361 362 /** 363 * Analyze hierarchical raw data, and compute per-function (flat) 364 * inclusive and exclusive metrics. 365 * 366 * Also, store overall totals in the 2nd argument. 367 * 368 * @param array $raw_data XHProf format raw profiler data. 369 * @param array &$overall_totals OUT argument for returning 370 * overall totals for various 371 * metrics. 372 * @return array Returns a map from function name to its 373 * call count and inclusive & exclusive metrics 374 * (such as wall time, etc.). 375 * 376 * @author Kannan Muthukkaruppan 377 */ 378 function xhprof_compute_flat_info($raw_data, &$overall_totals) { 379 380 global $display_calls; 381 382 $metrics = xhprof_get_metrics($raw_data); 383 384 $overall_totals = array( "ct" => 0, 385 "wt" => 0, 386 "ut" => 0, 387 "st" => 0, 388 "cpu" => 0, 389 "mu" => 0, 390 "pmu" => 0, 391 "samples" => 0 392 ); 393 394 // compute inclusive times for each function 395 $symbol_tab = xhprof_compute_inclusive_times($raw_data); 396 397 /* total metric value is the metric value for "main()" */ 398 foreach ($metrics as $metric) { 399 $overall_totals[$metric] = $symbol_tab["main()"][$metric]; 400 } 401 402 /* 403 * initialize exclusive (self) metric value to inclusive metric value 404 * to start with. 405 * In the same pass, also add up the total number of function calls. 406 */ 407 foreach ($symbol_tab as $symbol => $info) { 408 foreach ($metrics as $metric) { 409 $symbol_tab[$symbol]["excl_" . $metric] = $symbol_tab[$symbol][$metric]; 410 } 411 if ($display_calls) { 412 /* keep track of total number of calls */ 413 $overall_totals["ct"] += $info["ct"]; 414 } 415 } 416 417 /* adjust exclusive times by deducting inclusive time of children */ 418 foreach ($raw_data as $parent_child => $info) { 419 list($parent, $child) = xhprof_parse_parent_child($parent_child); 420 421 if ($parent) { 422 foreach ($metrics as $metric) { 423 // make sure the parent exists hasn't been pruned. 424 if (isset($symbol_tab[$parent])) { 425 $symbol_tab[$parent]["excl_" . $metric] -= $info[$metric]; 426 } 427 } 428 } 429 } 430 431 return $symbol_tab; 432 } 433 434 /** 435 * Hierarchical diff: 436 * Compute and return difference of two call graphs: Run2 - Run1. 437 * 438 * @author Kannan 439 */ 440 function xhprof_compute_diff($xhprof_data1, $xhprof_data2) { 441 global $display_calls; 442 443 // use the second run to decide what metrics we will do the diff on 444 $metrics = xhprof_get_metrics($xhprof_data2); 445 446 $xhprof_delta = $xhprof_data2; 447 448 foreach ($xhprof_data1 as $parent_child => $info) { 449 450 if (!isset($xhprof_delta[$parent_child])) { 451 452 // this pc combination was not present in run1; 453 // initialize all values to zero. 454 if ($display_calls) { 455 $xhprof_delta[$parent_child] = array("ct" => 0); 456 } else { 457 $xhprof_delta[$parent_child] = array(); 458 } 459 foreach ($metrics as $metric) { 460 $xhprof_delta[$parent_child][$metric] = 0; 461 } 462 } 463 464 if ($display_calls) { 465 $xhprof_delta[$parent_child]["ct"] -= $info["ct"]; 466 } 467 468 foreach ($metrics as $metric) { 469 $xhprof_delta[$parent_child][$metric] -= $info[$metric]; 470 } 471 } 472 473 return $xhprof_delta; 474 } 475 476 477 /** 478 * Compute inclusive metrics for function. This code was factored out 479 * of xhprof_compute_flat_info(). 480 * 481 * The raw data contains inclusive metrics of a function for each 482 * unique parent function it is called from. The total inclusive metrics 483 * for a function is therefore the sum of inclusive metrics for the 484 * function across all parents. 485 * 486 * @return array Returns a map of function name to total (across all parents) 487 * inclusive metrics for the function. 488 * 489 * @author Kannan 490 */ 491 function xhprof_compute_inclusive_times($raw_data) { 492 global $display_calls; 493 494 $metrics = xhprof_get_metrics($raw_data); 495 496 $symbol_tab = array(); 497 498 /* 499 * First compute inclusive time for each function and total 500 * call count for each function across all parents the 501 * function is called from. 502 */ 503 foreach ($raw_data as $parent_child => $info) { 504 505 list($parent, $child) = xhprof_parse_parent_child($parent_child); 506 507 if ($parent == $child) { 508 /* 509 * XHProf PHP extension should never trigger this situation any more. 510 * Recursion is handled in the XHProf PHP extension by giving nested 511 * calls a unique recursion-depth appended name (for example, foo@1). 512 */ 513 xhprof_error("Error in Raw Data: parent & child are both: $parent"); 514 return; 515 } 516 517 if (!isset($symbol_tab[$child])) { 518 519 if ($display_calls) { 520 $symbol_tab[$child] = array("ct" => $info["ct"]); 521 } else { 522 $symbol_tab[$child] = array(); 523 } 524 foreach ($metrics as $metric) { 525 $symbol_tab[$child][$metric] = $info[$metric]; 526 } 527 } else { 528 if ($display_calls) { 529 /* increment call count for this child */ 530 $symbol_tab[$child]["ct"] += $info["ct"]; 531 } 532 533 /* update inclusive times/metric for this child */ 534 foreach ($metrics as $metric) { 535 $symbol_tab[$child][$metric] += $info[$metric]; 536 } 537 } 538 } 539 540 return $symbol_tab; 541 } 542 543 544 /* 545 * Prunes XHProf raw data: 546 * 547 * Any node whose inclusive walltime accounts for less than $prune_percent 548 * of total walltime is pruned. [It is possible that a child function isn't 549 * pruned, but one or more of its parents get pruned. In such cases, when 550 * viewing the child function's hierarchical information, the cost due to 551 * the pruned parent(s) will be attributed to a special function/symbol 552 * "__pruned__()".] 553 * 554 * @param array $raw_data XHProf raw data to be pruned & validated. 555 * @param double $prune_percent Any edges that account for less than 556 * $prune_percent of time will be pruned 557 * from the raw data. 558 * 559 * @return array Returns the pruned raw data. 560 * 561 * @author Kannan 562 */ 563 function xhprof_prune_run($raw_data, $prune_percent) { 564 565 $main_info = $raw_data["main()"]; 566 if (empty($main_info)) { 567 xhprof_error("XHProf: main() missing in raw data"); 568 return false; 569 } 570 571 // raw data should contain either wall time or samples information... 572 if (isset($main_info["wt"])) { 573 $prune_metric = "wt"; 574 } else if (isset($main_info["samples"])) { 575 $prune_metric = "samples"; 576 } else { 577 xhprof_error("XHProf: for main() we must have either wt " 578 ."or samples attribute set"); 579 return false; 580 } 581 582 // determine the metrics present in the raw data.. 583 $metrics = array(); 584 foreach ($main_info as $metric => $val) { 585 if (isset($val)) { 586 $metrics[] = $metric; 587 } 588 } 589 590 $prune_threshold = (($main_info[$prune_metric] * $prune_percent) / 100.0); 591 592 // init_metrics($raw_data, null, null, false); 593 $flat_info = xhprof_compute_inclusive_times($raw_data); 594 595 foreach ($raw_data as $parent_child => $info) { 596 597 list($parent, $child) = xhprof_parse_parent_child($parent_child); 598 599 // is this child's overall total from all parents less than threshold? 600 if ($flat_info[$child][$prune_metric] < $prune_threshold) { 601 unset($raw_data[$parent_child]); // prune the edge 602 } else if ($parent && 603 ($parent != "__pruned__()") && 604 ($flat_info[$parent][$prune_metric] < $prune_threshold)) { 605 606 // Parent's overall inclusive metric is less than a threshold. 607 // All edges to the parent node will get nuked, and this child will 608 // be a dangling child. 609 // So instead change its parent to be a special function __pruned__(). 610 $pruned_edge = xhprof_build_parent_child_key("__pruned__()", $child); 611 612 if (isset($raw_data[$pruned_edge])) { 613 foreach ($metrics as $metric) { 614 $raw_data[$pruned_edge][$metric]+=$raw_data[$parent_child][$metric]; 615 } 616 } else { 617 $raw_data[$pruned_edge] = $raw_data[$parent_child]; 618 } 619 620 unset($raw_data[$parent_child]); // prune the edge 621 } 622 } 623 624 return $raw_data; 625 } 626 627 628 /** 629 * Set one key in an array and return the array 630 * 631 * @author Kannan 632 */ 633 function xhprof_array_set($arr, $k, $v) { 634 $arr[$k] = $v; 635 return $arr; 636 } 637 638 /** 639 * Removes/unsets one key in an array and return the array 640 * 641 * @author Kannan 642 */ 643 function xhprof_array_unset($arr, $k) { 644 unset($arr[$k]); 645 return $arr; 646 } 647 648 /** 649 * Type definitions for URL params 650 */ 651 define('XHPROF_STRING_PARAM', 1); 652 define('XHPROF_UINT_PARAM', 2); 653 define('XHPROF_FLOAT_PARAM', 3); 654 define('XHPROF_BOOL_PARAM', 4); 655 656 657 /** 658 * Internal helper function used by various 659 * xhprof_get_param* flavors for various 660 * types of parameters. 661 * 662 * @param string name of the URL query string param 663 * 664 * @author Kannan 665 */ 666 function xhprof_get_param_helper($param) { 667 $val = null; 668 if (isset($_GET[$param])) 669 $val = $_GET[$param]; 670 else if (isset($_POST[$param])) { 671 $val = $_POST[$param]; 672 } 673 return $val; 674 } 675 676 /** 677 * Extracts value for string param $param from query 678 * string. If param is not specified, return the 679 * $default value. 680 * 681 * @author Kannan 682 */ 683 function xhprof_get_string_param($param, $default = '') { 684 $val = xhprof_get_param_helper($param); 685 686 if ($val === null) 687 return $default; 688 689 return $val; 690 } 691 692 /** 693 * Extracts value for unsigned integer param $param from 694 * query string. If param is not specified, return the 695 * $default value. 696 * 697 * If value is not a valid unsigned integer, logs error 698 * and returns null. 699 * 700 * @author Kannan 701 */ 702 function xhprof_get_uint_param($param, $default = 0) { 703 $val = xhprof_get_param_helper($param); 704 705 if ($val === null) 706 $val = $default; 707 708 // trim leading/trailing whitespace 709 $val = trim($val); 710 711 // if it only contains digits, then ok.. 712 if (ctype_digit($val)) { 713 return $val; 714 } 715 716 xhprof_error("$param is $val. It must be an unsigned integer."); 717 return null; 718 } 719 720 721 /** 722 * Extracts value for a float param $param from 723 * query string. If param is not specified, return 724 * the $default value. 725 * 726 * If value is not a valid unsigned integer, logs error 727 * and returns null. 728 * 729 * @author Kannan 730 */ 731 function xhprof_get_float_param($param, $default = 0) { 732 $val = xhprof_get_param_helper($param); 733 734 if ($val === null) 735 $val = $default; 736 737 // trim leading/trailing whitespace 738 $val = trim($val); 739 740 // TBD: confirm the value is indeed a float. 741 if (true) // for now.. 742 return (float)$val; 743 744 xhprof_error("$param is $val. It must be a float."); 745 return null; 746 } 747 748 /** 749 * Extracts value for a boolean param $param from 750 * query string. If param is not specified, return 751 * the $default value. 752 * 753 * If value is not a valid unsigned integer, logs error 754 * and returns null. 755 * 756 * @author Kannan 757 */ 758 function xhprof_get_bool_param($param, $default = false) { 759 $val = xhprof_get_param_helper($param); 760 761 if ($val === null) 762 $val = $default; 763 764 // trim leading/trailing whitespace 765 $val = trim($val); 766 767 switch (strtolower($val)) { 768 case '0': 769 case '1': 770 $val = (bool)$val; 771 break; 772 case 'true': 773 case 'on': 774 case 'yes': 775 $val = true; 776 break; 777 case 'false': 778 case 'off': 779 case 'no': 780 $val = false; 781 break; 782 default: 783 xhprof_error("$param is $val. It must be a valid boolean string."); 784 return null; 785 } 786 787 return $val; 788 789 } 790 791 /** 792 * Initialize params from URL query string. The function 793 * creates globals variables for each of the params 794 * and if the URL query string doesn't specify a particular 795 * param initializes them with the corresponding default 796 * value specified in the input. 797 * 798 * @params array $params An array whose keys are the names 799 * of URL params who value needs to 800 * be retrieved from the URL query 801 * string. PHP globals are created 802 * with these names. The value is 803 * itself an array with 2-elems (the 804 * param type, and its default value). 805 * If a param is not specified in the 806 * query string the default value is 807 * used. 808 * @author Kannan 809 */ 810 function xhprof_param_init($params) { 811 /* Create variables specified in $params keys, init defaults */ 812 foreach ($params as $k => $v) { 813 switch ($v[0]) { 814 case XHPROF_STRING_PARAM: 815 $p = xhprof_get_string_param($k, $v[1]); 816 break; 817 case XHPROF_UINT_PARAM: 818 $p = xhprof_get_uint_param($k, $v[1]); 819 break; 820 case XHPROF_FLOAT_PARAM: 821 $p = xhprof_get_float_param($k, $v[1]); 822 break; 823 case XHPROF_BOOL_PARAM: 824 $p = xhprof_get_bool_param($k, $v[1]); 825 break; 826 default: 827 xhprof_error("Invalid param type passed to xhprof_param_init: " 828 . $v[0]); 829 exit(); 830 } 831 832 // create a global variable using the parameter name. 833 $GLOBALS[$k] = $p; 834 } 835 } 836 837 838 /** 839 * Given a partial query string $q return matching function names in 840 * specified XHProf run. This is used for the type ahead function 841 * selector. 842 * 843 * @author Kannan 844 */ 845 function xhprof_get_matching_functions($q, $xhprof_data) { 846 847 $matches = array(); 848 849 foreach ($xhprof_data as $parent_child => $info) { 850 list($parent, $child) = xhprof_parse_parent_child($parent_child); 851 if (stripos($parent, $q) !== false) { 852 $matches[$parent] = 1; 853 } 854 if (stripos($child, $q) !== false) { 855 $matches[$child] = 1; 856 } 857 } 858 859 $res = array_keys($matches); 860 861 // sort it so the answers are in some reliable order... 862 asort($res); 863 864 return ($res); 865 } 866
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |