Visualising Website Performance with Flame Graphs
Enforce Coding Standards with PHP_CodeSniffer and Eclipse IDE on Ubuntu Linux
Using PHP pspell Spell Check Functions with a Custom Dictionary
Development Resource Project
Changing Mailman Python Scripts for Virtual Host Support
A Simple ISAPI Filter for Authentication on IIS

Profiling PHP using XDebug and Webgrind

Monday, 15 September 14, 8:00 pm
Derick Rethans' Xdebug is a really useful PHP extension that lets you step through code line-by-line as it executes, watching variables and seeing exactly what's going on.

Line-by-line debugging isn't the only way this extension allows you to examine and improve your code though, as it can also profile your code to let you see how much time each part of your script takes to execute. Assuming you already have Xdebug installed - it's available through PECL if you don't - you have to add the following lines to the xdebug section of your php.ini to enable the profiler:
[xdebug] xdebug.profiler_enable = 0 xdebug.profiler_enable_trigger = 1 xdebug.profiler_output_name = xdebug.out.%t xdebug.profiler_output_dir = /tmp
Notice that xdebug.profiler_enable is set to 0. This is because we don't want Xdebug running all the time as all the work it does will result in a noticeable slowdown on site performance. Instead, we want to only run the profiler when we want it, hence we have xdebug.profiler_enable_trigger set to 1. With this configuration, the profiler will only run when we request a page with XDEBUG_PROFILE passed as either a GET or POST parameter, or as a cookie. The other options control the name and path where the profiler dumps should be saved to. I recommend leaving these as they are, as it's what Webgrind expects when it looks for profile files.

As always, you must restart your web server in order to make the changes to php.ini take effect. Then, in your browser, request a page that you want to profile but pass XDEBUG_PROFILE on the querystring e.g. http://localhost/mywebsite/index.php?XDEBUG_PROFILE. You should now find a profile dump in /tmp. This file will be quite big, and not very readable to human eyes. That's where Webgrind comes in.

Note: On up-to-date systems, your web server may well not save directly to /tmp, and you may instead find the dumps have been placed at a location something like /tmp/systemd-private-c27535b4f640466381956d69f48c8cf3-httpd.service-kLO7je/tmp which is only readable by root. This is a security measure to protect session data from unauthorised users. You could run this command to move the profile dumps into /tmp proper:
sudo find /tmp -name "*xdebug*" -exec mv {} /tmp \;
However, if you're going to use Webgrind to analyse the data, this command is not necessary, because Webgrind is also a web application and therefore will find the dumps just fine where they are.

Making Sense of Your Profile Data

There are several choices for viewing profile dumps in a more accessible format than trying to read the raw data in a text editor, the most notable of which are KCachegrind, and Webgrind. KCachegrind is a desktop application, which can be installed from most package managers if you are on Linux. However, as its name suggests, it's a KDE application, and so requires all the other ~200 Mb of KDE gubbins to run.

If you'd rather not have all this stuff cluttering up your file system, or you're on Windows, Webgrind is an acceptable alternative. While it doesn't offer all the features of KCachegrind, it comes as a simple PHP app and is therefore KDE-dependency-free and cross-platform. I recommend installing it directly from the Github repo, for example:
cd /tmp git clone https://github.com/jokkedk/webgrind.git sudo mv /tmp/webgrind/ /srv/http/
Cloning into tmp and then moving it to my web server root means that the Webgrind folder maintains the user and group ownership of my normal user, allowing me to easily edit files, run git pull and so on, without compromising web server security. I then create a symlink to this folder from the projects directory in my home directory, where I can open it in my IDE should I need to.

Now you can access the Webgrind UI by visiting http://localhost/webgrind in your browser. Click the Update button to have it analyse the most recent profile file, and display a breakdown of where 90% of the script processing time was spent.


By default, it shows the times as a percentage of the script execution time. The 'self cost' figure represents the time spent on code inside the function (or method) itself, and the 'inclusive cost' shows the time spent including calls to other functions appearing elsewhere in the data - thus adding up the 'inclusive cost' will come to more than 100%.

Visualising Website Performance

The tables of performance metrics presented by Webgrind can be useful for highlighting the worst offenders slowing down your web page, but they do not readily give you the full picture of how it all fits together. For that, a graphical visualisation of the data is more appropriate.

Graphviz

Webgrind can turn its profiling output to a dot graph using Graphviz. Once you have Graphviz installed (you should find it in most Linux package managers), pressing the Show Call Graph button in Webgrind will render the call graph as an SVG image in a new window:

Please enter your comment in the box below. Comments will be moderated before going live. Thanks for your feedback!

Cancel Post

/xkcd/ The Maritime Approximation