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.
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.
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.
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 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.
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=0xdebug.profiler_enable_trigger=1xdebug.profiler_output_dir=/path/to/profiler/results
xdebug.profiler_enable = 0This 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 = 1This 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/resultsThis 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.
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.
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.
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
Homebrew is a package manager for OS X. We discuss Homebrew in Appendix A.
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.
The easiest way to install XHProf is with your operating system’s package manager (assuming you installed PHP the same way):
# Ubuntusudo apt-get install build-essential;sudo pecl install mongo;sudo pecl install xhprof-beta;# CentOSsudo 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.soextension=mongo.so
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;cdxhgui;php install.php;
The XHGUI web application has a webroot/ directory. Update your web server virtual host’s document root to this directory.
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(){returnrand(0,100)===42;},
Change these lines to:
'profiler.enable'=>function(){returntrue;// <-- Run on every request},
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.
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_paramPHP_VALUE"auto_prepend_file=/var/sites/xhgui/external/header.php";
Or you can set this in your Apache virtual host configuration:
php_admin_valueauto_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.
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.
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.
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:
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.