Faster PHP Apps – Profile Your Code with Xdebug

Object-oriented programming is well and truly in fashion, and PHP is no exception. So you’ve adopted the proper design patterns, built your site on the latest PHP framework, and have your database access abstracted so far that you’ve forgotten SQL.

What’s Going On?

When you first move towards object-oriented programming, the first thing you might notice is that you can give yourself a headache trying to follow the execution path through your code and the framework it’s built on.

The next thing you might notice is that your site isn’t any faster – in fact perhaps it’s slower than it was. Object-oriented programming generally aims to improve the quality, maintainability and reusability of code, but sometimes this comes at the price of some raw speed.

So we’ve got potentially slower code, and we can no longer just open up our simple PHP script and follow its execution from the top of the file to the bottom. How do we figure out exactly what’s going on inside?

Xdebug

Xdebug 2 (currently beta – I’m running 2.0.0RC3) is an indispensable PHP extension which provides various ways of debugging and analysing your code on your development server. Today, we’re interested in profiling information for PHP scripts.

Installing Xdebug on your apache/PHP development server is beyond the scope of this post, but a quick ‘sudo pecl install xdebug-beta’ and a one line edit to my php.ini got it up and running on my Ubuntu 6.10 virtual machine.

Once you have Xdebug 2 installed, the following lines in your .htaccess will turn on auto profiling for all requests handled by PHP:


php_value xdebug.profiler_output_dir /tmp
php_value xdebug.profiler_output_name timestamp
php_value xdebug.profiler_enable 1

Now to open the output files that are appearing in the /tmp directory…

WinCacheGrind

WinCacheGrind is the simplest way to get useful information out of your cachegrind output file. It provides a simple tree view of the PHP execution with references to class, function and filenames. Most importantly, it tells you how long each function call took.

WinCacheGrind example

KCachegrind

If you’re running KDE (on Linux, or Mac OS X via fink if you’re daring), you might like to give KCachegrind a try. It is much more complicated than WinCacheGrind, but presents your cachegrind data in some very interesting ways.

In this example the callmap view clearly shows that SQL queries through mysql_query() are responsible for most of the execution time.
Xdebug call map example

Here we see part of a callgraph, showing function interaction.
Xdebug call graph example

Less Grinding, More Caching

And the easiest way to get your code running faster? Cache, cache and more cache.

Use your new tools to find the slow points in your scripts. Make sure slow queries take advantage of your MySQL query cache. Try out a PHP bytecode cache like APC. Cache your PHP objects with memcached. Cache common sections of your generated HTML. Cache entire pages before sending them. Make your users cache your pages with Expires, ETag and Last-Modified HTTP headers. The more layers of caching the better.

More Xdebug

Xdebug does much more than output profiling data – I see it as the Firebug for backend developers. I recommend anybody working with PHP set it up on their development server, even if only for the colourful PHP error reporting with full stack traces:

Xdebug error reporting

And by the looks of this Google Summer of Code Project, live interactive debugging with Xdebug will soon be available to all.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • auricle
  • clynx

    I fully agree, profiling can be a very good way to enhance applications. Just as a small addition, PHPEdit supports xDebug and the profiling features since the new version is released. If you are interested into it you might take a look at our screencast.

  • Andrei Zmievski

    It should also be mentioned that Xdebug by default profiles only one request cycle. Sometimes it is useful to look at the usage pattern over several requests. In order to do that, set xdebug.profiler_aggregate = 1 in the .ini file, restart Apache, execute several requests, and then stop Apache. You will see a .cachegrind.aggregate file in the profiler directory.

  • Matt

    Works flawlessly, thanks for writing this up. Will come in very handy!

  • malikyte

    According to the xdebug installation documentation, it doesn’t work with APC (and (m)any other Zend modules). Has this been rectified in recent versions (of PHP and/or the modules)? I can (and do) use xdebug on my development machine, but haven’t been able to use APD.

  • http://www.sitepoint.com/ Paul Annesley

    As far as I know, Xdebug and APC are still considered incompatible with each other.

    I would tend to run Xdebug without APC on a development server anyway. Then the staging server would mirror the live production server as closely as possible, with APC but no Xdebug.

    Of course, these servers could all be on the same physical machine thanks to virtualization.

  • http://www.medikoo.com mariuszn3

    I’m running Xdebug and Apc without problems (so far).
    Win/PHP 5.2.1, APC 3.0.14, Xdebug 2.0.0RC1

  • http://www.saumendra.com Saumendra Swain

    Yes Xdebug do output profiling data as like FireBug. Saves lot of time and Money.

  • MattC

    I recently discover Xdebug and was blown away by it’s profiling abilities. This article really only skims the surface and I think misses the point by suggesting query caching and APC as primary ways to improve performance. I have written a full counterpoint at http://www.pseudocoder.com/archives/2007/04/24/how-to-really-use-xdebug-to-speed-up-your-app/