Modern PHP (2015)
Part III. Deployment, Testing, and Tuning
Chapter 11. Profiling
Profiling is how we analyze application performance. It is a great way to debug performance issues and pinpoint bottlenecks in your application code. In other words, if your application is slow, use a profiler to figure out why. Profilers let us traverse the entire PHP call stack, and they tell us which functions or methods are called, in what order, how many times, with what arguments, and for how long. We can also see how much memory and CPU are used throughout the application request lifecycle.
When to Use a Profiler
You don’t need to profile your PHP applications immediately. You only profile PHP applications if there is a performance issue that is otherwise hard to diagnose. How do you know if you have a performance issue? Some issues are obvious (e.g., a database query takes too long). Other issues may not be as obvious.
You can detect performance issues with benchmarking tools like Apache Bench and Siege. A benchmarking tool allows you to test your application performance externally, much as an application user would with a web browser. Benchmarking tools let you set the number of concurrent users and total number of requests that hit a specific application URL. When the benchmarking tool finishes, it tells you the number of requests per second that your application sustained (among other statistics). If you find a particular URL sustains only a small number of requests per second, you may have a performance issue. If the performance issue is not immediately obvious, you use a profiler.
Types of Profilers
There are two types of profilers. There are those that should run only during development, and there are those that can run during production.
Xdebug is a popular PHP profiling tool written by Derick Rethans, but it should only be used as a profiler during development because it consumes a lot of system resources to analyze your application. Xdebug profiler results are not human-readable, so you’ll need an application to parse and display the results. KCacheGrind and WinCacheGrind are good applications for visualizing Xdebug profiler results.
XHProf is a popular PHP profiler written by Facebook. It is intended to be run during development and production. XHProf’s profiler results are also not human-readable, but Facebook provides a companion web application called XHGUI to visualize and compare profiler results. I’ll talk more about XHGUI later in this chapter.
NOTE
Both Xdebug and XHProf are PHP extensions, and you can install them with your operating system’s package manager. They can also be installed with pecl.
Xdebug
Xdebug is one of the most popular PHP profilers, and it makes it easy to analyze your application’s call stack to find bottlenecks and performance issues. Refer to Example 10-1 in Chapter 10 for Xdebug installation instructions.
Configure
Xdebug configuration lives in your php.ini file. Here are the Xdebug profiler configuration settings I recommend. Make sure you specify your own profiler output directory. Restart your PHP process after saving these settings:
xdebug.profiler_enable = 0
xdebug.profiler_enable_trigger = 1
xdebug.profiler_output_dir = /path/to/profiler/results
xdebug.profiler_enable = 0
This instructs Xdebug to not run automatically. We don’t want Xdebug to run automatically on each request, because that would drastically decrease performance and impede development.
xdebug.profiler_enable_trigger = 1
This instructs Xdebug to run on-demand. We can activate Xdebug profiling per-request by adding the XDEBUG_PROFILE=1 query parameter to any of our PHP application’s URLs. When Xdebug detects this query parameter, it profiles the current request and generates a report in the output directory specified by the xdebug.profiler_output_dir setting.
xdebug.profiler_output_dir = /path/to/profiler/results
This is the directory path that contains generated profiler results. Profiler reports can be massive (e.g., 500 MB or larger) for complex PHP applications. Make sure you change this value to the correct filesystem path for your application.
TIP
I recommend you keep profiler results beneath your PHP application’s topmost directory. This makes it easy to find and review profiler results while developing your application.
Trigger
The Xdebug profiler does not run automatically because the xdebug.profiler_enable setting is 0. We trigger the Xdebug profiler for a single request by adding the XDEBUG_PROFILE=1 query parameter to any PHP application URL. An example HTTP request URL might be/users/show/1?XDEBUG_PROFILE=1. When Xdebug detects the XDEBUG_PROFILE query parameter, it activates and runs the profiler for the current request. The profiler results are dumped into the directory specified by the xdebug.profiler_output_dir setting.
Analyze
The Xdebug profiler generates results in the CacheGrind format. You’ll need a CacheGrind-compatible application to review the profiler results. Some good applications for reviewing CacheGrind files are:
§ WinCacheGrind for Windows
§ KCacheGrind for Linux
§ WebGrind for web browsers
Mac OS X users can install KCacheGrind with Homebrew using this command:
brew install qcachegrind
TIP
Homebrew is a package manager for OS X. We discuss Homebrew in Appendix A.
XHProf
XHProf is a newer PHP application profiler. It is created by Facebook and is intended to be run during both development and production. It does not collect as much information as Xdebug’s profiler, but it consumes fewer system resources, making it suitable for production environments.
Install
The easiest way to install XHProf is with your operating system’s package manager (assuming you installed PHP the same way):
# Ubuntu
sudo apt-get install build-essential;
sudo pecl install mongo;
sudo pecl install xhprof-beta;
# CentOS
sudo yum groupinstall 'Development Tools';
sudo pecl install mongo;
sudo pecl install xhprof-beta;
Append these lines to your php.ini file, and restart your PHP process to load the new extensions:
extension=xhprof.so
extension=mongo.so
XHGUI
XHProf is most useful when paired with XHGUI, Facebook’s companion web application used to review and compare XHProf profiler output. XHGUI is a PHP web application and requires:
§ Composer
§ Git
§ MongoDB
§ PHP 5.3+
§ PHP mongo extension
I assume these system requirements are installed. I also assume the XHGUI web application lives in the /var/sites/xhgui/ directory. This directory path is probably different on your server, so keep that in mind:
cd /var/sites;
git clone https://github.com/perftools/xhgui.git;
cd xhgui;
php install.php;
The XHGUI web application has a webroot/ directory. Update your web server virtual host’s document root to this directory.
Configure
Open XHGUI’s config/config.default.php file in a text editor. By default, XHProf collects data for only 1% of all HTTP requests. This is fine for production, but you may want to collect data more frequently during development. You can increase XHProf’s data collection by editing these lines in the config/config.default.php file:
'profiler.enable' => function() {
return rand(0, 100) === 42;
},
Change these lines to:
'profiler.enable' => function() {
return true; // <-- Run on every request
},
TIP
XHProf assumes your PHP application runs on a single server. It also assumes your MongoDB database does not require authentication. If your MongoDB server does require authentication, update the Mongo database connection in the config/config.default.php file.
Trigger
You must include the XHGUI web application’s external/header.php file at the very beginning of your PHP application. It’s easiest to use PHP’s auto_prepend_file INI configuration setting. You can set this in the php.ini configuration file:
auto_prepend_file = /var/sites/xhgui/external/header.php
Or you can set this in your nginx virtual host configuration:
fastcgi_param PHP_VALUE "auto_prepend_file=/var/sites/xhgui/external/header.php";
Or you can set this in your Apache virtual host configuration:
php_admin_value auto_prepend_file "/var/sites/xhgui/external/header.php"
Restart PHP, and XHProf will begin collecting and saving information into its MongoDB database. You can review and compare XHProf runs at the XHGUI virtual host’s URL.
New Relic Profiler
Another popular PHP profiler is New Relic. This is actually a web service that uses a custom operating system daemon and PHP extension to hook into your PHP application and report data back to the web service. Unlike Xdebug and XHProf, New Relic’s PHP profiler is not free. That being said, I adore New Relic and recommend it if your budget allows. Like XHProf, New Relic’s PHP profiler is meant to be run during production, and it gives you a near real-time view of your application’s performance with a really nice online dashboard. Learn more on New Relic’s website.
Blackfire Profiler
As I am writing this book, Symfony is currently testing a new PHP profiler called Blackfire. It provides unique visualization tools to help discover application bottlenecks. I hear it’s looking like a really good alternative to Xdebug and XHProf. Keep an eye on this one.
Further Reading
I hope I’ve introduced you to PHP profiling in this chapter so that you feel comfortable finding, installing, and using a PHP profiler most appropriate for your application. Here are a few links to help you learn more about PHP profiling:
§ http://www.sitepoint.com/the-need-for-speed-profiling-with-xhprof-and-xhgui/
§ https://blog.engineyard.com/2014/profiling-with-xhprof-xhgui-part-1
§ https://blog.engineyard.com/2014/profiling-with-xhprof-xhgui-part-2
§ https://blog.engineyard.com/2014/profiling-with-xhprof-xhgui-part-3
What’s Next
At this point we’ve talked a lot about modern PHP, including new features, good practices, provisioning, tuning, deployment, testing, and profiling. I hope you have filled your brain with tons of fun ideas to implement in your next PHP applications.
Now I want to take a few minutes to chat about the future of PHP. A lot is happening in the PHP ecosystem. The future of PHP is unfolding as we speak thanks to forward-looking projects like PHP 7, HHVM, Hack, and the PHP-FIG. Let’s explore HHVM and Hack, specifically, and figure out what they mean for PHP’s future.