PhpRiot
News Archive
PhpRiot Newsletter
Your Email Address:

More information

Profiling with XHGui

Note: This article was originally published at Planet PHP on 3 December 2010.
Planet PHP

Everyone wants a fast web site. Making one is a bit more difficult. Profiling code during development is easy, thanks to the excellent Xdebug extension (which also provides handy debugging tools), but this still leaves us blind in production, where we care the most. It's also frequently more than a little different than the development machine.

Facebook faced a similar problem in their pre-HipHop days, and developed XHProf, a profiler lightweight enough to run on your production servers. It still adds load to the server when it runs, but the tradeoff is worth it, because you'll know why your pages are slow. XHProf can record different levels of detail about your app for different levels of performance sacrifice. I generally run it full out, because I prefer the highest level of detail, and I accept the performance hit.

XHProf will need to be compiled and configured on your server. This is currently trivial on most Linux-like servers. A Windows version is in the works (it already works apart from returning zero for the number of CPU ticks). Once the extension is installed and confirmed through phpinfo(), you're off to the races. It's also capable of showing you a call graph if you have Graphviz installed. While you're playing on the server, you may want to look for this.

The included GUI works, but it only provides information on a run-by-run basis, and it uses serialized data on disk for storage. I'd heartily recommend XHGui for your UI needs.

XHGui includes two components, a data recorder (in the /external directory) and a UI for display (/xhprof_lib and /xhprof_html).

The recorder is used to actually profile your page loads. The easiest way to do this is to set PHP to automatically prepend header.php and append the footer.php. This can be trivially accomplished with two Apache directives for a given virtual host:

php_value auto_prepend_file "/var/www/xh.example.com/external/header.php" php_value auto_append_file "/var/www/xh.example.com/external/footer.php"

The UI directories contain a config file (in /xhprof_lib). You'll need to copy config.sample.php to config.php and make the appropriate changes. There are a bunch of settings to be aware of:

exceptionURLs These URLs will never have the link to the result page displayed at the bottom, even for administrators. This is useful for URLs that return non-html output, such as images, videos, XML, &c. exceptionPostURLs The app records GET, POST, and cookie information when profiling a page. This is useful in determining exactly why a given code path was used. For example, it may reveal that a user was logged in, or submitted a form comment. POST data, however, will occasionally include privileged information such as login credentials. The URLs listed here will prevent saving their POST data. controlIPs The ability to turn profiling on or off and to display the link to profile results is restricted to users accessing the page from within a control IP. Add IPs here to give yourself control. When you're in the controlIP list, you'll be able to turn profiling on for all your requests by appending ?_profile=1 to a URL (you'll be given a cookie and redirected back to the original page); a link to the results for that run will also be appended to the page. weight One of every $weight requests will be profiled.

There are two functions within the configuration file that are designed to be edited on each install:

_urlSimilator This function accepts the URL of a requested resource. You should collapse URLs in such a way that functionally-identical endpoints return the same value. For example, if /blog/?post=25 and /blog/?post=26 are just two blog posts, you can probably assume that these URLs follow an identical path within PHP. The only difference is a parameter passed to the database (or, hopefully, memcached). Supply the _urlSimilator with as much intelligence as you can to help it collapse these URLs. _aggregateCalls This function controls the pie chart within a specific run. The goal is to collapse pie slices together to give the developer a better idea of how certain sections of your app are doing. For example, you may choose to collapse mysql_*

Truncated by Planet PHP, read more at the original (another 5191 bytes)