index.html 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. <html>
  2. <title>
  3. XHProf Documentation (Draft)
  4. </title>
  5. <body>
  6. <h3>XHProf Documentation (Draft)</h3>
  7. <b>Contents</b>
  8. <ol>
  9. <li><a href="#introduction">Introduction</a></li>
  10. <li><a href="#overview">XHProf Overview</a></li>
  11. <li><a href="#installation">Installing the XHProf extension</a></li>
  12. <li><a href="#using_extension">Profiling using XHProf</a></li>
  13. <li><a href="#ui_setup">Setting up the XHProf UI</a></li>
  14. <li><a href="#production_notes">Notes on using XHProf in production</a></li>
  15. <li><a href="#sampling_mode">Lightweight Sampling Mode</a>
  16. <li><a href="#misc">Additional features</a></li>
  17. <li><a href="#dependencies">Dependencies</a></li>
  18. <li><a href="#credits">Acknowledgements</a></li>
  19. </ol>
  20. <ol>
  21. <li><a name="introduction"><h2>Introduction</h2></a>
  22. <p>XHProf is a hierarchical profiler for PHP. It reports
  23. function-level call counts and <a href="#inclusive">inclusive</a> and
  24. <a href="#exclusive">exclusive</a> metrics such as wall (elapsed)
  25. time, CPU time and memory usage. A function's profile can be broken
  26. down by callers or callees. The raw data collection component is
  27. implemented in C as a PHP Zend extension called
  28. <code><b>xhprof</b></code>. XHProf has a simple HTML based user
  29. interface (written in PHP). The browser based UI for viewing profiler
  30. results makes it easy to view results or to share results with peers.
  31. A callgraph image view is also supported.
  32. <p>XHProf reports can often be helpful in understanding the structure
  33. of the code being executed. The hierarchical nature of the reports can
  34. be used to determine, for example, what chain of calls led to a
  35. particular function getting called.
  36. <p>XHProf supports ability to compare two runs (a.k.a. "diff" reports)
  37. or aggregate data from multiple runs. Diff and aggregate reports, much
  38. like single run reports, offer "flat" as well as "hierarchical" views
  39. of the profile.
  40. <p>XHProf is a light-weight instrumentation based profiler. During the
  41. data collection phase, it keeps track of call counts and inclusive
  42. metrics for arcs in the dynamic callgraph of a program. It computes
  43. exclusive metrics in the reporting/post processing phase. XHProf
  44. handles recursive functions by detecting cycles in the callgraph at
  45. data collection time itself and avoiding the cycles by giving unique
  46. depth qualified names for the recursive invocations.
  47. </p>
  48. <p>XHProf's light-weight nature and aggregation capabilities make it
  49. well suited for collecting "function-level" performance statistics
  50. from production environments. [See <a
  51. href="#production_notes">additional notes</a> for use in production.]
  52. <ul>
  53. <hr>
  54. <p>XHProfLive (not part of the open source kit), for example, is a
  55. system-wide performance monitoring system in use at Facebook that is
  56. built on top of XHProf. XHProfLive continually gathers function-level
  57. profiler data from production tier by running a sample of page
  58. requests under XHProf. XHProfLive then aggregates the profile data
  59. corresponding to individual requests by various dimensions such a
  60. time, page type, and can help answer a variety of questions such as:
  61. What is the function-level profile for a specific page? How expensive
  62. is function "foo" across all pages, or on a specific page? What
  63. functions regressed most in the last hour/day/week? What is the
  64. historical trend for execution time of a page/function? and so on.
  65. <hr>
  66. </ul>
  67. <p>Originally developed at Facebook, XHProf was open sourced in Mar, 2009.</p>
  68. </ul>
  69. <li><a name="overview"><h2>XHProf Overview</h2></a>
  70. <p>XHProf provides:
  71. <ul>
  72. <li><b>Flat profile</b> (<a href="sample-flat-view.jpg" >screenshot</a>)
  73. <p>Provides function-level summary information such number of calls,
  74. inclusive/exclusive wall time, memory usage, and CPU time.
  75. <p><li><b>Hierarchical profile (Parent/Child View)</b>
  76. (<a href="sample-parent-child-view.jpg" >screenshot</a>)
  77. <p>For each function, it provides a breakdown of calls and times per
  78. parent (caller) & child (callee), such as:
  79. <ul>
  80. <li> what functions call a particular function and how many times?
  81. <li> what functions does a particular function call?
  82. <li> The total time spent under a function when called from a particular parent.
  83. </ul>
  84. <p><li><b>Diff Reports</b>
  85. <p>You may want to compare data from two XHProf runs for various
  86. reasons-- to figure out what's causing a regression between one
  87. version of the code base to another, to evaluate the performance
  88. improvement of a code change you are making, and so on.
  89. <p>A diff report takes two runs as input and provides both flat
  90. function-level diff information, and hierarchical information
  91. (breakdown of diff by parent/children functions) for each function.
  92. <p>The "flat" view (<a href="sample-diff-report-flat-view.jpg"
  93. >sample screenshot</a>) in the diff report points out the top
  94. regressions & improvements.
  95. <p>Clicking on functions in the "flat" view of the diff report, leads
  96. to the "hierarchical" (or parent/child) diff view of a function (<a href="sample-diff-report-parent-child-view.jpg"
  97. >sample screenshot</a>). We can get a
  98. breakdown of the diff by parent/children functions.
  99. <p><li><b>Callgraph View</b> (<a href="sample-callgraph-image.jpg"
  100. >sample screenshot</a>)
  101. <p>The profile data can also be viewed as a callgraph. The callgraph
  102. view highlights the critical path of the program.
  103. <p><li><b>Memory Profile</b>
  104. <p>XHProf's memory profile mode helps track functions that
  105. allocate lots of memory.
  106. <p>It is worth clarifying that that XHProf doesn't strictly track each
  107. allocation/free operation. Rather it uses a more simplistic
  108. scheme. It tracks the increase/decrease in the amount of memory
  109. allocated to PHP between each function's entry and exit. It also
  110. tracks increase/decrease in the amount of <b>peak</b> memory allocated to
  111. PHP for each function.
  112. <li>XHProf tracks <code>include, include_once, require and
  113. require_once</code> operations as if they were functions. The name of
  114. the file being included is used to generate the name for these <a
  115. href="#include_funcs">"fake" functions</a>.
  116. </ul>
  117. <a name="Terminology"></a><h2>Terminology</h2>
  118. <ol>
  119. <a name="inclusive"></a><li><b>Inclusive Time (or Subtree Time)</b>:
  120. Includes time spent in the function as well as in descendant functions
  121. called from a given function.
  122. <a name="exclusive"></a><li><b>Exclusive Time/Self Time</b>: Measures
  123. time spent in the function itself. Does not include time in descendant
  124. functions.
  125. <li><b>Wall Time</b>: a.k.a. Elapsed time or wall clock time.
  126. <li><b>CPU Time</b>: CPU time in user space + CPU time in kernel space
  127. </ol>
  128. <a name="Naming_convention_for_special_functions"></a><h2>Naming convention for special functions</h2>
  129. <ol>
  130. <p><li><code><b>main()</b></code>: a fictitious function that is at the root of the call graph.
  131. <a name="include_funcs"></a>
  132. <p><li><code><b>load::&lt;filename&gt;</b></code>
  133. and <code><b>run_init::&lt;filename&gt;</b></code>:
  134. <p>XHProf tracks PHP <code>include/require</code> operations as
  135. function calls.
  136. <p>For example, an <b>include "lib/common.php";</b> operation will
  137. result in two XHProf function entries:
  138. <ul>
  139. <li> <code><b>load::lib/common.php</b></code> - This represents the work done by the
  140. interpreter to compile/load the file. [Note: If you are using a PHP
  141. opcode cache like APC, then the compile only happens on a cache miss
  142. in APC.]
  143. <li> <code><b>run_init::lib/common.php</b></code> - This represents
  144. initialization code executed at the file scope as a result of the
  145. include operation.
  146. </ul>
  147. <p><li><code><b>foo@&lt;n&gt;</b></code>: Implies that this is a
  148. recursive invocation of <code>foo()</code>, where <code>&lt;n&gt;</code> represents
  149. the recursion depth. The recursion may be direct (such as due to
  150. <code>foo()</code> --&gt; <code>foo()</code>), or indirect (such as
  151. due to </code>foo()</code> --&gt; <code>goo()</code> --&gt; foo()).
  152. </ol>
  153. <a name="Limitations"></a><h2>Limitations</h2>
  154. <p>True hierarchical profilers keep track of a full call stack at
  155. every data gathering point, and are later able to answer questions
  156. like: what was the cost of the 3rd invokation of foo()? or what was
  157. the cost of bar() when the call stack looked like
  158. a()-&gt;b()-&gt;bar()?
  159. </p>
  160. <p>XHProf keeps track of only 1-level of calling context and is
  161. therefore only able to answer questions about a function looking
  162. either 1-level up or 1-level down. It turns out that in practice this
  163. is sufficient for most use cases.
  164. </p>
  165. <p>To make this more concrete, take for instance the following
  166. example.
  167. </p>
  168. <pre>
  169. Say you have:
  170. 1 call from a() --&gt; c()
  171. 1 call from b() --&gt; c()
  172. 50 calls from c() --&gt; d()
  173. </pre>
  174. <p>While XHProf can tell you that d() was called from c() 50 times, it
  175. cannot tell you how many of those calls were triggered due to a()
  176. vs. b(). [We could speculate that perhaps 25 were due to a() and 25
  177. due to b(), but that's not necessarily true.]
  178. </p>
  179. <p>In practice however, this isn't a very big limitation.
  180. </p>
  181. <li><a name="installation"><h2>Installing the XHProf Extension</h2></a>
  182. <p> The extension lives in the "extension/" sub-directory.
  183. <ul><hr>
  184. <p><b>Note:</b> A windows port hasn't been implemented yet. We have
  185. tested <code>xhprof</code> on <b>Linux/FreeBSD</b> so far.
  186. <p>Version 0.9.2 and above of XHProf is also expected to work on <b>Mac
  187. OS</b>. [We have tested on Mac OS 10.5.]
  188. <p><b>Note:</b> XHProf uses the RDTSC instruction (time stamp counter)
  189. to implement a really low overhead timer for elapsed time. So at the
  190. moment <code>xhprof</code> only works on <b>x86</b> architecture.
  191. Also, since RDTSC values may not be synchronized across CPUs,
  192. <code>xhprof</code> binds the program to a single CPU during the
  193. profiling period.
  194. <p>XHProf's RDTSC based timer functionality doesn't work correctly if
  195. <b>SpeedStep</b> technology is turned on. This technology is available on
  196. some Intel processors. [Note: Mac desktops and laptops typically have
  197. SpeedStep turned on by default. To use XHProf, you'll need to disable
  198. SpeedStep.]
  199. <hr></ul>
  200. <p> The steps
  201. below should work for Linux/Unix environments.
  202. <pre>
  203. % cd &lt;xhprof_source_directory&gt;/extension/
  204. % phpize
  205. % ./configure --with-php-config=&lt;path to php-config&gt;
  206. % make
  207. % make install
  208. % make test
  209. </pre>
  210. <p><a name="ini_file"></a><b>php.ini file</b>: You can update your
  211. php.ini file to automatically load your extension. Add the following
  212. to your php.ini file.
  213. <pre>
  214. [xhprof]
  215. extension=xhprof.so
  216. ;
  217. ; directory used by default implementation of the iXHProfRuns
  218. ; interface (namely, the XHProfRuns_Default class) for storing
  219. ; XHProf runs.
  220. ;
  221. xhprof.output_dir=&lt;directory_for_storing_xhprof_runs&gt;
  222. </pre>
  223. <li><a name="using_extension"><h2>Profiling using XHProf</h2></a>
  224. <p>Test generating raw profiler data using a sample test program like:
  225. <ul>
  226. <p><b>foo.php</b>
  227. <pre>
  228. &lt;?php
  229. function bar($x) {
  230. if ($x > 0) {
  231. bar($x - 1);
  232. }
  233. }
  234. function foo() {
  235. for ($idx = 0; $idx < 2; $idx++) {
  236. bar($idx);
  237. $x = strlen("abc");
  238. }
  239. }
  240. // start profiling
  241. <b>xhprof_enable();</b>
  242. // run program
  243. foo();
  244. // stop profiler
  245. <b>$xhprof_data = xhprof_disable();</b>
  246. // display raw xhprof data for the profiler run
  247. print_r($xhprof_data);
  248. </pre>
  249. </ul>
  250. <p><b>Run the above test program:</b>
  251. <pre>
  252. % php -dextension=xhprof.so foo.php
  253. </pre>
  254. <p><b>You should get an output like:</b>
  255. <pre>
  256. Array
  257. (
  258. [foo==>bar] => Array
  259. (
  260. [ct] => 2 # 2 calls to bar() from foo()
  261. [wt] => 27 # inclusive time in bar() when called from foo()
  262. )
  263. [foo==>strlen] => Array
  264. (
  265. [ct] => 2
  266. [wt] => 2
  267. )
  268. [bar==>bar@1] => Array # a recursive call to bar()
  269. (
  270. [ct] => 1
  271. [wt] => 2
  272. )
  273. [main()==>foo] => Array
  274. (
  275. [ct] => 1
  276. [wt] => 74
  277. )
  278. [main()==>xhprof_disable] => Array
  279. (
  280. [ct] => 1
  281. [wt] => 0
  282. )
  283. [main()] => Array # fake symbol representing root
  284. (
  285. [ct] => 1
  286. [wt] => 83
  287. )
  288. )
  289. </pre>
  290. <p><b>Note:</b> The raw data only contains "inclusive" metrics. For
  291. example, the wall time metric in the raw data represents inclusive
  292. time in microsecs. Exclusive times for any function are computed
  293. during the analysis/reporting phase.
  294. <p><b>Note:</b> By default only call counts & elapsed time is profiled.
  295. You can optionally also profile CPU time and/or memory usage. Replace,
  296. <ul><pre>
  297. <b>xhprof_enable();</b>
  298. </pre></ul>
  299. in the above program with, for example:
  300. <ul><pre>
  301. <b>xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY)</b>;
  302. </pre></ul>
  303. <p><b>You should now get an output like:</b>
  304. <pre>
  305. Array
  306. (
  307. [foo==>bar] => Array
  308. (
  309. [ct] => 2 # number of calls to bar() from foo()
  310. [wt] => 37 # time in bar() when called from foo()
  311. [cpu] => 0 # cpu time in bar() when called from foo()
  312. [mu] => 2208 # change in PHP memory usage in bar() when called from foo()
  313. [pmu] => 0 # change in PHP peak memory usage in bar() when called from foo()
  314. )
  315. [foo==>strlen] => Array
  316. (
  317. [ct] => 2
  318. [wt] => 3
  319. [cpu] => 0
  320. [mu] => 624
  321. [pmu] => 0
  322. )
  323. [bar==>bar@1] => Array
  324. (
  325. [ct] => 1
  326. [wt] => 2
  327. [cpu] => 0
  328. [mu] => 856
  329. [pmu] => 0
  330. )
  331. [main()==>foo] => Array
  332. (
  333. [ct] => 1
  334. [wt] => 104
  335. [cpu] => 0
  336. [mu] => 4168
  337. [pmu] => 0
  338. )
  339. [main()==>xhprof_disable] => Array
  340. (
  341. [ct] => 1
  342. [wt] => 1
  343. [cpu] => 0
  344. [mu] => 344
  345. [pmu] => 0
  346. )
  347. [main()] => Array
  348. (
  349. [ct] => 1
  350. [wt] => 139
  351. [cpu] => 0
  352. [mu] => 5936
  353. [pmu] => 0
  354. )
  355. )
  356. </pre>
  357. <p><b>Skipping builtin functions during profiling</b>
  358. <p>By default PHP builtin functions (such as <code>strlen</code>) are
  359. profiled. If you do not want to profile builtin functions (to either
  360. reduce the overhead of profiling further or size of generated raw
  361. data), you can use the <code><b>XHPROF_FLAGS_NO_BUILTINS</b></code>
  362. flag as in for example:
  363. <ul><pre>
  364. // do not profile builtin functions
  365. <b>xhprof_enable(XHPROF_FLAGS_NO_BUILTINS)</b>;
  366. </pre></ul>
  367. <p><b>Ignoring specific functions during profiling (0.9.2 or higher)</b>
  368. <p>Starting with release 0.9.2 of xhprof, you can tell XHProf to
  369. ignore a specified list of functions during profiling. This allows you
  370. to ignore, for example, functions used for indirect function calls
  371. such as <code>call_user_func</code> and
  372. <code>call_user_func_array</code>. These intermediate functions
  373. unnecessarily complicate the call hierarchy and make the XHProf
  374. reports harder to interpret since they muddle the parent-child
  375. relationship for functions called indirectly.
  376. <p> To specify the list of functions to be ignored during profiling
  377. use the 2nd (optional) argument to <code>xhprof_enable</code>.
  378. For example,
  379. <pre>
  380. <ul><pre>
  381. <b>
  382. // elapsed time profiling; ignore call_user_func* during profiling
  383. xhprof_enable(0,
  384. array('ignored_functions' => array('call_user_func',
  385. 'call_user_func_array')));
  386. </b>
  387. or,
  388. <b>
  389. // elapsed time + memory profiling; ignore call_user_func* during profiling
  390. xhprof_enable(XHPROF_FLAGS_MEMORY,
  391. array('ignored_functions' => array('call_user_func',
  392. 'call_user_func_array')));
  393. </b>
  394. </pre></ul>
  395. </li>
  396. <li><a name="ui_setup"><h2>Setting up XHProf UI</h2></a>
  397. <ol>
  398. <li><b>PHP source structure</b>
  399. <p>The XHProf UI is implemented in PHP. The code resides in two
  400. subdirectories, <code>xhprof_html/</code> and <code>xhprof_lib/</code>.
  401. <p>The <code>xhprof_html</code> directory contains the 3 top-level PHP pages.
  402. <ul>
  403. <li><code>index.php</code>: For viewing a single run or diff report.
  404. <li><code>callgraph.php</code>: For viewing a callgraph of a XHProf run as an image.
  405. <li><code>typeahead.php</code>: Used implicitly for the function typeahead form
  406. on a XHProf report.
  407. </ul>
  408. <p>The <code>xhprof_lib</code> directory contains supporting code for
  409. display as well as analysis (computing flat profile info, computing
  410. diffs, aggregating data from multiple runs, etc.).
  411. <li><p><b>Web server config: </b> You'll need to make sure that the
  412. <code>xhprof_html/</code> directory is accessible from your web server, and that
  413. your web server is setup to serve PHP scripts.
  414. <li><p><b>Managing XHProf Runs</b>
  415. <p>Clients have flexibility in how they save the XHProf raw data
  416. obtained from an XHProf run. The XHProf UI layer exposes an interface
  417. iXHProfRuns (see xhprof_lib/utils/xhprof_runs.php) that clients can
  418. implement. This allows the clients to tell the UI layer how to fetch
  419. the data corresponding to a XHProf run.
  420. <p>The XHProf UI libaries come with a default file based
  421. implementation of the iXHProfRuns interface, namely
  422. "XHProfRuns_Default" (also in xhprof_lib/utils/xhprof_runs.php).
  423. This default implementation stores runs in the directory specified by
  424. <a href="#ini_file"><b>xhprof.output_dir</b></a> INI parameter.
  425. <p>A XHProf run must be uniquely identified by a namespace and a run
  426. id.
  427. <p><b>a) Saving XHProf data persistently</b>:
  428. <p>Assuming you are using the default implementation
  429. <code><b>XHProfRuns_Default</b></code> of the
  430. <code><b>iXHProfRuns</b></code> interface, a typical XHProf run
  431. followed by the save step might look something like:
  432. <pre>
  433. // start profiling
  434. xhprof_enable();
  435. // run program
  436. ....
  437. // stop profiler
  438. $xhprof_data = xhprof_disable();
  439. //
  440. // Saving the XHProf run
  441. // using the default implementation of iXHProfRuns.
  442. //
  443. include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php";
  444. include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php";
  445. $xhprof_runs = new <b>XHProfRuns_Default()</b>;
  446. // Save the run under a namespace "xhprof_foo".
  447. //
  448. // **NOTE**:
  449. // By default save_run() will automatically generate a unique
  450. // run id for you. [You can override that behavior by passing
  451. // a run id (optional arg) to the save_run() method instead.]
  452. //
  453. <b>$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");</b>
  454. echo "---------------\n".
  455. "Assuming you have set up the http based UI for \n".
  456. "XHProf at some address, you can view run at \n".
  457. "http://&lt;xhprof-ui-address&gt;/index.php?run=$run_id&source=xhprof_foo\n".
  458. "---------------\n";
  459. </pre>
  460. <p>The above should save the run as a file in the directory specified
  461. by the <code><b>xhprof.output_dir</b></code> INI parameter. The file's
  462. name might be something like
  463. <b><code>49bafaa3a3f66.xhprof_foo</code></b>; the two parts being the
  464. run id ("49bafaa3a3f66") and the namespace ("xhprof_foo"). [If you
  465. want to create/assign run ids yourself (such as a database sequence
  466. number, or a timestamp), you can explicitly pass in the run id to the
  467. <code>save_run</code> method.
  468. <p><b>b) Using your own implementation of iXHProfRuns</b>
  469. <p> If you decide you want your XHProf runs to be stored differently
  470. (either in a compressed format, in an alternate place such as DB,
  471. etc.) database, you'll need to implement a class that implements the
  472. iXHProfRuns() interface.
  473. <p> You'll also need to modify the 3 main PHP entry pages (index.php,
  474. callgraph.php, typeahead.php) in the "xhprof_html/" directory to use
  475. the new class instead of the default class <code>XHProfRuns_Default</code>.
  476. Change this line in the 3 files.
  477. <pre>
  478. $xhprof_runs_impl = new XHProfRuns_Default();
  479. </pre>
  480. <p>You'll also need to "include" the file that implements your class in
  481. the above files.
  482. <li><p><b>Accessing runs from UI</b>
  483. <p><b>a) Viewing a Single Run Report</b>
  484. <p>To view the report for run id say &lt;run_id&gt; and namespace
  485. &lt;namespace&gt; use a URL of the form:
  486. <p><code>
  487. http://&lt;xhprof-ui-address&gt;/index.php?run=&lt;run_id&gt;&source=&lt;namespace&gt;
  488. </code>
  489. <p>For example,
  490. <p><code>
  491. http://&lt;xhprof-ui-address&gt;/index.php?run=49bafaa3a3f66&source=xhprof_foo
  492. </code>
  493. <p><b>b) Viewing a Diff Report</b>
  494. <p>To view the report for run ids say &lt;run_id1&gt; and
  495. &lt;run_id2&gt; in namespace &lt;namespace&gt; use a URL of the form:
  496. <p><code>
  497. http://&lt;xhprof-ui-address&gt;/index.php?<b>run1=&lt;run_id1&gt;&run2=&lt;run_id2&gt;</b>&source=&lt;namespace&gt;
  498. </code>
  499. <p><b>c) Aggregate Report</b>
  500. <p>You can also specify a set of run ids for which you want an aggregated view/report.
  501. <p>Say you have three XHProf runs with ids 1, 2 & 3 in namespace
  502. "benchmark". To view an aggregate report of these runs:
  503. <ul><p><code>
  504. http://&lt;xhprof-ui-address&gt;/index.php?<b>run=1,2,3</b>&source=benchmark
  505. </code></p></ul>
  506. <p><b>Weighted aggregations</b>: Further suppose that the above three runs
  507. correspond to three types of programs p1.php, p2.php and p3.php that
  508. typically occur in a mix of 20%, 30%, 50% respectively. To view an
  509. aggregate report that corresponds to a weighted average of these runs
  510. using:
  511. <ul><p><code>
  512. http://&lt;xhprof-ui-address&gt;/index.php?<b>run=1,2,3&wts=20,30,50</b>&source=benchmark
  513. </code></p></ul>
  514. </ol>
  515. <li><a name="production_notes"><h2>Notes on using XHProf in production</h2></a>
  516. <p>Some observations/guidelines. Your mileage may vary:
  517. <ul>
  518. <li>CPU timer (getrusage) on Linux has high overheads. It is also
  519. coarse grained (millisec accuracy rather than microsec level) to be
  520. useful at function level. Therefore, the skew in reported numbers
  521. when using XHPROF_FLAGS_CPU mode tends to be higher.
  522. <p>We recommend using elapsed time + memory profiling mode in
  523. production. [Note: The additional overhead of memory profiling
  524. mode is really low.]
  525. <p><ul><pre><b>
  526. // elapsed time profiling (default) + memory profiling
  527. xhprof_enable(XHPROF_FLAGS_MEMORY);
  528. </b></pre>
  529. </ul></p>
  530. <li>Profiling a random sample of pages/requests works well in capturing
  531. data that is representative of your production workload.
  532. <p>To profile say 1/10000 of your requests, instrument the beginning of
  533. your request processing with something along the lines of:
  534. <p><ul><pre><code>
  535. if (mt_rand(1, 10000) == 1) {
  536. xhprof_enable(XHPROF_FLAGS_MEMORY);
  537. $xhprof_on = true;
  538. }
  539. </code></pre></ul></p>
  540. <p>At the end of the request (or in a request shutdown function), you might
  541. then do something like:
  542. <p><ul><pre><code>
  543. if ($xhprof_on) {
  544. // stop profiler
  545. $xhprof_data = xhprof_disable();
  546. // save $xhprof_data somewhere (say a central DB)
  547. ...
  548. }
  549. </code></pre></ul></p>
  550. <p> You can then rollup/aggregate these individual profiles by time
  551. (e.g., 5 minutely/hourly/daily basis), page/request type,or other
  552. dimensions using <a href="#xhprof_aggregate_runs"><code><b>xhprof_aggregate_runs()</b></code></a>.
  553. </ul>
  554. <li><a name="sampling_mode"><h2>Lightweight Sampling Mode</h2></a>
  555. <p>The xhprof extension also provides a very light weight <b>sampling
  556. mode</b>. The sampling interval is 0.1 secs. Samples record the full
  557. function call stack. The sampling mode can be useful if an extremely
  558. low overhead means of doing performance monitoring and diagnostics is
  559. desired.
  560. <p> The relevant functions exposed by the extension for using the
  561. sampling mode are <code><b>xhprof_sample_enable()</b></code> and
  562. <code><b>xhprof_sample_disable()</b></code>.
  563. <p>[<b>TBD</b>: more detailed documentation on sampling mode.]
  564. <li><a name="misc"><h2>Additional Features</h2></a></li>
  565. <p>The <code><b>xhprof_lib/utils/xhprof_lib.php</b></code> file contains
  566. additional library functions that can be used for manipulating/
  567. aggregating XHProf runs.
  568. <p>For example:
  569. <ul>
  570. <a name="xhprof_aggregate_runs"></a>
  571. <p><li><code><b>xhprof_aggregate_runs()</b></code>:
  572. can be used to aggregate multiple XHProf runs into a single run. This
  573. can be helpful for building a system-wide "function-level" performance
  574. monitoring tool using XHProf. [For example, you might to roll up
  575. XHProf runs sampled from production periodically to generate hourly,
  576. daily, reports.]
  577. <p><li><code><b>xhprof_prune_run()</b></code>: Aggregating large number of
  578. XHProf runs (especially if they correspond to different types of
  579. programs) can result in the callgraph size becoming too large. You can
  580. use <code>xhprof_prune_run</code> function to prune the callgraph data
  581. by editing out subtrees that account for a very small portion of the
  582. total time.
  583. </ul>
  584. <ol>
  585. </ol>
  586. <li><a name="dependencies"><h2>Dependencies</h2></a></li>
  587. <ul>
  588. <li><b>JQuery Javascript</b>: For tooltips and function name
  589. typeahead, we make use of JQuery's javascript libraries. JQuery is
  590. available under both a MIT and GPL licencse
  591. (http://docs.jquery.com/Licensing). The relevant JQuery code, used by
  592. XHProf, is in the <code>xhprof_html/jquery</code> subdirectory.
  593. <li><b>dot (image generation utility):</b> The callgraph image
  594. visualization ([View Callgraph]) feature relies on the presence of
  595. Graphviz "dot" utility in your path. "dot" is a utility to
  596. draw/generate an image for a directed graph.
  597. </ul>
  598. <li><a name="credits"><h2>Acknowledgements</h2></a>
  599. <p>The HTML-based navigational interface for browsing profiler results
  600. is inspired by that of a similar tool that exists for Oracle's stored
  601. procedure language, PL/SQL. But that's where the similarity ends; the
  602. internals of the profiler itself are quite different.
  603. </li>
  604. </ol>
  605. </body>
  606. </html>