Wednesday, June 4, 2008

PHP Code Performance Profiling on Ubuntu

A few options for code profiling in PHP:

XDebug

XDebug consists of a PHP extension, and requires an XDebug client to view the output generated by XDebug. It writes profiling data by default to /tmp. What we want to do is install XDebug, enable profiling and view the files generated using Kcachegrind, which is an XDebug client that comes default with Ubuntu.

To install XDebug on Ubuntu is as simple as the command:

sudo apt-get install php5-xdebug
This assumes you installed Apache2 and PHP5 using aptitude. Otherwise you'd probably want to follow one of these instructions on installing XDebug:
http://ubuntuforums.org/showthread.php?t=525257
http://2bits.com/articles/setting-up-xdebug-dbgp-for-php-on-debian-ubuntu.html
http://www.apaddedcell.com/easy-php-debugging-ubuntu-using-xdebug-and-vim

Once you've installed xdebug you will need to enable php code profiling by setting the xdebug.profiler_enable setting to 1 in php.ini. You can view the php.ini settings using the command:

php -r 'phpinfo();'
To narrow down to just the xdebug settings use:
php -r 'phpinfo();' | grep xdebug
Note: php --info | xdebug will work also.

If you used the simple sudo apt-get install php5-xdebug to install xdebug, then it should have automatically created an ini file: /etc/php5/conf.d/xdebug.ini which is included with the php.ini.

Edit the php.ini file or /etc/php5/conf.d/xdebug.ini and add the line:

xdebug.profiler_enable=1
Example: sudo gedit /etc/php5/conf.d/xdebug.ini

After saving this you will need to restart Apache in order to reload the php settings.

sudo /etc/init.d/apache2 restart

You will then need an xdebug client to display the profiling information. Kcachegrind is installed by default in Ubuntu. Open Kcachegrind kcachegrind & and use it to open a file generated by xdebug. This will be found in the directory specified in php.ini for the directive xdebug.trace_output_dir which defaults to /tmp. The files generated by Xdebug are prefixed with cachegrind.out.. So you can view a list of these files using the command ls /tmp | grep cachegrind.out.

How to interpret the Xdebug profiling information displayed in Kcachegrind is described at: http://www.xdebug.org/docs/profiler under Analysing Profiles.

Benchmark

Benchmark is a Pear package. Documentation is found at: http://pear.php.net/package/Benchmark/docs/latest/Benchmark/Benchmark_Profiler.html

A simple usage would be:

// load class and instantiate and instance
require_once 'Benchmark/Profiler.php';
$profiler = new Benchmark_Profiler();

// start profiling
$profiler->start();

// do some stuff
myFunction();

// stop
$profiler->stop();

// display directly in PHP output
$profiler->display();

myFunction could look something like:
function myFunction() {
     global $profiler;

     $profiler->enterSection('myFunction');

     //do something
     $profiler->leaveSection('myFunction');

     return;
 }

Benchmark allows you to do profiling directly in your PHP script. One of the disadvantages of XDebug is that you have to enable profiling in PHP.ini and it would start creating profiling dump files in /tmp. These files over time could get very large if you forget to turn off XDebug. Unfortunately you can't set the XDebug profiling directive, xdebug.profiler_enable directly in PHP with ini_set().

Benchmark would seem like a bit more work compared to XDebug, however, if working with large code bases. The advantage of being able to apply it to a single file however makes it ideal for profiling live php websites. You could easily track down a problem occuring on a live site without having to recreate and simulate the live site and data in a development environment.

For example you could have Benchmark only display profiling data if requested via the URL:

// load class and instantiate and instance
require_once 'Benchmark/Profiler.php';
$profiler = new Benchmark_Profiler();

// start profiling
$profiler->start();

// do some stuff
myFunction();

// stop
$profiler->stop();

// only display if requested by me
if (isset($_GET['debug'])) $profiler->display();

I haven't got around to the other two alternatives for PHP code profiling. I will update this entry if I do.

1 comment:

Unknown said...

Here is a great article on using XDebug with Eclipse and the PDT plugin.
http://devzone.zend.com/article/2930-Debugging-PHP-applications-with-xdebug