[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/externals/xhprof/ -> xhprof_lib.php (source)

   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  


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1