PHP Profiling with Cachegrind and XDebug

Often clients ask me to speed up their websites.  In most cases I use a backend to frontend approach. To get a general overview why a website might be slow I usually start by generating a code profile and analyzing it in Wincachegrind/Kcachegrind. This is in my opinion the fastest way to isolate slow code sections.

To generate the code profile you need to have XDebug installed. The following example shows how to install and configure XDebug for Ubuntu. To keep things simple I assume PHP + Apache are already set up and running. In case you are not running Ubuntu you might need to adjust this.

First install the XDebug PHP module:

root@michael:~# apt-get install php5-xdebug

The next step is to configure XDebug (don’t forget to restart Apache after).

/etc/php5/conf.d/xdebug.ini (Ubuntu)

xdebug.profiler_enable="0"
xdebug.profiler_output_dir="/tmp/xdebug"
xdebug.profiler_output_name="cachegrind.out.%p"
xdebug.profiler_enable_trigger="1"
xdebug.profiler_append="0"
xdebug.profiler_aggregate="0"

Once this is done add the XDEBUG_PROFILE query string to the URL of the page you want to profile.

http://example.com/test.php?XDEBUG_PROFILE=1

XDebug will now generate a code profile in /tmp. In case this doesn’t work double check if Apache has write permissions to the /tmp directory. The file should be called cachegrind.out.[ApacheProcessId]. I do most of my GUI stuff in Windows and use Wincachegrind to visualize my code profiles. Wincachegrind isn’t maintained any more and its last release dates back to 2009, but it still does the trick. Another popular alternative is KCachegrind which provides a neat visual call tree. I prefer Wincachegrind though as it is much easier to follow the code flow. The XDebug profiler documentation page  maintains a full list of alternatives.

Here a screenshot of Wincachegrind visualizing an example code profile.

WinCachegrind profiling session

Note: for security reasons, don’t enable XDebug profiling on live sites. Generating the code profiles is very resource intensive and having profiling enabled might enable an attacker to perform a DOS attack.

PHP Profiling with Cachegrind and XDebug

PHP Remote Debugging in VIM with XDebug

XDebugs remote debugging feature is very helpful when trying to trace code in an unknown application or debugging a tricky problem. It works with most IDEs but can also be set up to work with Vim.

To get it working you need to install the XDebug Apache module:

root@michael:~# apt-get install php5-xdebug

and configure the XDebug config (/etc/php5/conf.d/xdebug.ini) for remote debugging:

xdebug.remote_enable="1"
xdebug.remote_host="localhost"
xdebug.remote_port="9000"
xdebug.remote_mode="req"
xdebug.remote_autostart="0"
xdebug.remote_log="/tmp/xdebug_remote.log"

The remote_host needs to be the hostname or IP where Vim is running. The Vim debugging plugin listens on port 9000. Make sure your firewall settings allow for connections to this host and port. The req mode starts the debugger for every request.

Next you need to download and install the DBGp Remote Debugger Interface plugin for Vim. There are several different versions available. Make sure to use the latest version by Hadi Zeftin. To do so, download the file and copy its contents into your Vim plugin directory (~/.vim/plugin/). If you want to make the plugin available to all users on your system you can also copy the plugin files to the central vim plugin directory (/usr/share/vim/vim73/plugin/).

You can make various adjustments if you like. I prefer to set the debugger timeout to 20s and the array/object depth to 10. You can change this by adding the following line to your ~/.vimrc:

let g:debuggerTimeout = 20
let g:debuggerMaxDepth = 10

Next you need enable the debugging mode by calling your script with the ?XDEBUG_SESSION_START=1 query parameter.

http://www.example.com/?XDEBUG_SESSION_START=1

You only need to do this once and debugging will be enabled for 1 hour. You can change this time by setting a different xdebug.remote_cookie_expire_time in your xdebug.ini. There are also various browser plugins (Chrome, Firefox) available to enable and disable the debugging mode but in my opinion the query parameter is easy enough.

Once this is done you can open the file you want to debug in Vim and hit F5. You should see a status message like this:

waiting for a new connection on port 9000 for 20 seconds...

Next call your script in your browser and Vim should switch into debugging mode.

You can trace the code by using F2-F4. F12 lets you inspect the property under your cursor. Once you are in debug mode you can also open other files, set breakpoints and run the program till hitting the breakpoint by hitting F5. To set a breakpoint switch to command mode and enter Bp (:Bp).

PHP Remote Debugging in VIM with XDebug