Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/externals/xhprof/xhprof_lib.php
12233 views
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
867
868