How to setup and use the Xdebug Extension for PHP Profiling

A profiling tool can provide valuable information about bottlenecks in your code. I believe profiling is a critical aspect of optimizing because it will tell you about your real code bottlenecks as opposed to your perceived bottlenecks. This enables you to focus your resources on areas that will provide the most performance benefit for your effort. Most programming languages and environments have one or more profiling tools available and PHP is no exception.

Xdebug is a PHP extension that provides valuable debugging information such as stack traces, functions traces, profiling, code coverage analysis, etc. There is another PHP tool called DBG that has similar functionality but this post will focus on using Xdebug.

Setup Xdebug

Xdebug is a PECL module and can be installed using the PECL installation instructions in one of my previous posts.

  • If you have already setup PEAR you just need to run the following from a shell:
    sudo pecl install xdebug

    If everything goes well Xdebug should download, build, and install. You may get a message telling you:

    You should add "extension=xdebug.so" to php.ini

    Go ahead and add the line. On an Ubuntu server you will probably find the php.ini file here: /etc/php5/apache2/php.ini

  • Restart Apache, or whatever web server you are using, so the change will take effect.
    If you are running Apache on Ubuntu it would be:

    sudo /etc/init.d/apache2 restart
  • Write a phpinfo.php page with the following code and then point a browser at it. It should show the Xdebug module there in addition to many other things:
    <?php phpinfo(); ?>

At this point the Xdebug extension should be installed. For more detailed instructions on a PECL extension install see my post: How to install a PHP PECL extension/module on Ubuntu. Note that there is a problem running the Xdebug extension with Zend Studio since it has it’s own debugger.

Enable Xdebug profiling

  • By default, profiling is disable in Xdebug. Enable it by adding the following entry to the php.ini file:
    xdebug.profiler_enable=On

    On on a linux box there is often a php.d or conf.d folder that holds additional .ini file settings PHP will use. On Ubuntu the path for this folder is “/etc/php5/apache2/conf.d”. To prevent further cluttering my php.ini file with Xdebug settings, I created a xdebug.ini file to store all my Xdebug .ini file settings. This file is located in the “/etc/php5/apache2/conf.d” so it is automatically scanned when Apache is restarted.

    Now you might be tempted to enable the profiler in your script using the ini_set() function which, normally allows you to temporarily set a .ini setting for only the current script execution. Unfortunately this does not work. You must set it in the php.ini or a sub .ini file and restart the web server.

  • Restart your web server (I.e. Apache) once you have “xdebug.profiler_enable” set to “On”.

By default, Xdebug will write a cachegrind.out file to the /tmp folder. It will be named something like cachegrind.out.22373 where the number at the end is the ID of the process that was profiled. If you are using Windows you will probably need to change the default folder. Also by default, this file will be overwritten by each script execution so you don’t have to worry about it getting too big. The output file behavior is highly customizable and a complete list of Xdebug settings can be found here.

Call your script and display the analysis

With Xdebug enabled, pull up the page in your browser that you want to profile. If everything is working OK a cachegrind.out file should show up in the /tmp folder.

There are a couple programs you can use to open and analyze the cachegrind file:

WinCacheGrind

WinCacheGrind is not very featured but it will tell you the main thing you need to know, which is where your PHP application is spending its time. Click on the screen shot below to see the full output of my test script:

wincachegrind screen shot

The script makes an external call to example.com using a file_get_contents() function. Based on this analysis I might try caching the call results and only make the call at some interval to keep the cache updated. This would eliminate almost 75% of the application’s overhead and is just one example of an easy-to-fix bottleneck that profiling will help identify.

KCacheGrind

KCacheGrind does essentially the same thing as WinCacheGrind but it is geared for the Linux desktop and has quite a few more bells and whistles:

kcachegrind screen shot

KCacheGrind includes a map feature that graphically represents the percentages of where the test application spent the time:

kcachegrind screen shot

KCacheGrind also includes a graph feature with an export option that displays a tree diagram of the linkage between all the includes and functions:

kcachegrindexport1.jpg

That’s it for this post. Have fun profiling!

Leave a Reply