# Profiling PHP with Xdebug and Webgrind

Finding and fixing performance bottlenecks in PHP web applications can be both time-consuming and difficult. Fortunately, free tools like Xdebug and Webgrind allow you to easily find and visualize bottlenecks in your PHP scripts.

Webgrind is an Xdebug profiling web frontend in PHP5. It implements a subset of the features of kcachegrind and installs in seconds and works on all platforms.–Webgrind

Anyone who has ever needed to profile code is probably familiar with KcacheGrind (a profile data visualization tool). KcacheGrind provides a way to visualize the profile data from a program execution, allowing you to quickly and easily see where the program is spending its time. Knowing where the execution bottlenecks are allows you to focus your optimization efforts in the correct places.

For a long time, the Xdebug extension for PHP has been able to (among other things) dump execution profile information to disk in a format that is usable by KcacheGrind, which is great if you are running Linux with KDE.

The webgrind project provides a web-based replacement for KcacheGrind that can be installed on any operating system, allowing you to visualize a portion of the Xdebug profiling data through a browser.

## Installation

Before using webgrind, you must first install Xdebug.

Installing webgrind is pretty simple:

2. Unzip webgrind in your web server’s document root
3. Configure Xdebug and webgrind
4. Point your browser to where you installed webgrind

## Configuration

Unfortunately, webgrind does not often work “out-of-the-box”… There are a few configuration details that need to be dealt with in order to start profiling your code. The following PHP configuration directives can be used to control the behavior of Xcebug:

xdebug.profiler_enable
This directive actually turns on Xdebug’s internal profiler. You must set this to 1 in order to have Xdebug actually produce output for webgrind to analyze.
xdebug.profiler_enable_trigger
If you enable this option, profiles will only be generated if you pass a GET/POST parameter or cookie with the name XDEBUG_PROFILE, e.g., http://localhost/script.php?XDEBUG_PROFILE. You must not enable xdebug.profiler_enable if you use this option.
xdebug.profiler_output_dir
This directive tells Xdebug where to put the profile data. By default, it is set to ‘/tmp’, which is usually fine. If you want, you can probably omit this from your Xdebug configuration.
xdebug.profiler_output_name
This value tells Xdebug how to create filenames for the data it writes to disk. By default, the value is set to cachegrind.out.%p, where %p will be replaced with the process ID. This is bad, and you will definitely need to change it. The problem is that Apache processes serve multiple requests, so each request in a given process will overwrite the profiling data from previous requests. Other possible format specifiers can be used.
xdebug.profiler_append
Enabling this option will cause xdebug to append data to the output file if it already exists (the default behavior is to overwrite the output file). This is a handy option if you need to average out the profiling data over multiple script executions. In that case, be sure to set xdebug.profiler_output_name using a format that will ensure that each successive page load uses the same profiler output name, e.g., cachegrind.out.%s.

Assuming you have already loaded the Xdebug extension, the following additional PHP configuration directives should be a good starting point for you:

xdebug.profiler_enable = 1
xdebug.profiler_output_name = cachegrind.out.%t.%p


That’s it, you should be ready to profile your PHP code with Xdebug and Cachegrind!

Chris Abernethy
PHP Wrangler, MySQL DBA, Linux SysAdmin and all around computer guy, developing LAMP applications since Slackware came on 10 floppy disks.

### 28 Comments on "Profiling PHP with Xdebug and Webgrind"

1. Thanks for the clear explanation.

2. Diglin says:

xdebug.profiler_enable=On
; Provide the appropriate path of your tmp directory
xdebug.profiler_output_dir=”/usr/local/php5/tmp”
xdebug.profiler_append=On
xdebug.profiler_output_name = cachegrind.out.%t.%p
; Use XDEBUG_PROFILE in GET or POST parameter to activate the profile log
; ex: URL: test.php?XDEBUG_PROFILE
xdebug.profiler_enable_trigger=On

To activate the profiler for a script you have to give a parameter in the url:
ex. http://localhost/script.php?XDEBUG_PROFILE

And the profiler will be realized.

3. Brownoxford says:

Thanks for the additional information Diglin, I’ve updated the post to include information on xdebug_profiler_append and xdebug_profiler_enable_trigger.

4. Piotr says:

Hi, I’ve got a huge problem with webgrind. I got the xdebug installed and working – it creates its output files im predefinied directory. But i can’t get webgrind to work – it doeasn’t see the xdebug output files, althought they’re are there. Help, i’m stuck

5. Jm says:

to Piotr:
Had the same problem, just realized that if xdebug.profiler_enable is set to 1, debugging is done on webgrind and it cannot read the cachegrind files because they are files in use.
Profiler must not run on webgrind.
Hope it helps!

6. Brownoxford says:

@Piotr:

What value do you have for your profiler_output_name configuration parameter? I had a similar issue as well, and found that this parameter needs to be set so that loads of webgrind itself never use the same output filename as the page you are trying to profile.

You can either conditionally profile pages using profiler_enable = 0 and profile_enable_trigger = 1 as Jim suggests, or you can use profiler_output_name = cachegrind.out.%t.%p

I’d definitely be interested in hearing if those options do not work for you!

Hi

I got it to work with the following configuration in both /apache/bin/php.ini AND /php/php.ini:

zend_extension_ts=”\path\to\ext\php_xdebug.dll”
xdebug.remote_enable=true
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000
xdebug.remote_handler=dbgp
xdebug.profiler_enable=1
xdebug.profiler_output_name = cachegrind.out.%t.%p
xdebug.profiler_output_dir=”C:\xampp\tmp”

8. What value do you have for your profiler_output_name configuration parameter? I had a similar issue as well, and found that this parameter needs to be set so that loads of webgrind itself never use the same output filename as the page you are trying to profile.

9. Brownoxford says:

I usually use cachegrind.out.%t.%p when I want one output file per script run, but if I want to run a script multiple times and see the aggregate numbers I use cachegrind.out.%s and set xdebug.profiler_append = on

10. Steve Tran says:

I’m on a ubuntu box, I’ve configured xdebug exactly as above

xdebug.profiler_output_name=cachegrind.out.%t.%p
xdebug.profiler_append=On

yet, when running localhost/webgrind, it only lists of the .out files from this script
/usr/share/obm/www/cron/cron.php

So frustrated….

11. Brownoxford says:

@Steve: Do you also have xdebug.profiler_enable=1 in your configuration?

12. Ben Rexin says:

Nice to know, for different cachegrind files per host you can use %H in the profiler_output_name, according to http://www.xdebug.org/docs/all_settings#trace_output_name

13. Housing says:

можно в Гугле еще поискать..

14. Hello,

I am running Ubuntu 9.10 and have installed everything as stated above. Everything seems to be working to the point that the grind files are generated. However when I go into webgrinds web interface and click update it just shows a message telling me to select a grind file. No matter which file I choose I get the same message. I have verified that the grind files actually contain data. I am not sure if there is a permissions problem reading them or not.

jocrawfo@jcrawford:~/installed/webgrind/grinds$namei -m ~/installed/webgrind/grinds/cachegrind.out.1268144184.18372 f: /home/jocrawfo/installed/webgrind/grinds/cachegrind.out.1268144184.18372 drwxr-xr-x / drwxr-xr-x home drwxrwxr-x jocrawfo drwxr-xr-x installed drwxr-xr-x webgrind drwxrwxrwx grinds jocrawfo@jcrawford:~/installed/webgrind$ ls -la | grep grinds
drwxrwxr-x 2 www-data www-data 4096 2010-03-09 09:26 grinds

Any assistance would be appreciated.

Thanks,
Joseph Crawford

15. Bart McLeod says:

This is slightly off topic, but maybe you can help. I have installed XDebug for php5.3.2VC9TS on a windows 7 box and I use a virtual Ubuntu 9.04 with kcachegrind installed to produce the visuals.

But when I enable the profiler I get not output in the browser. I do get output files that I can produce visuals of. But the browser says the connection was reinitialized during the request and refuses output.

Any idea’s?

This is in my php.ini:

[XDebug]
zend_extension=d:\php532\ext\php_xdebug-2.0.5-5.3-vc9.dll ; if xdebug enabled, webserver doesn’t output
xdebug.profiler_enable=1
xdebug.profiler_output_dir=d:\tmp
xdebug.profiler_output_name = cachegrind.out.%t.%p

16. alexandrov says:

Also please do not forget Webgrind may have no permissions to read profiler output files. For example if these files are located not in Webgrind server root.

So, the default php open_basedir restriction may be in effect.

If so, add to configuration of VirtualHost

 php_admin_value open_basedir none 
Or in similar way set profiler output files accessible from webgrind installation.

17. Sarah Walsh says:

Thanks for all the help above.

I’ve been hair pulling for the last 2 days to get Webgrind running, receiving a file read error on xdebug.profiler_output_dir.

The solution (for me at least): changing xdebug.remote_host from ‘localhost’ to 127.0.0.1. It’s probably written somewhere but I suffer from the disease of !RTFM

18. ali says:

Hi Dear,
I am completely new to webgrind and Xdebug so want some help from you guys.
First clear me the os in which i should install the webgrind and then
the file and location in which we have to make the modifications.
Note:I am currently using wamp server.

19. ft says:

Hi Ali,

Which Os are you using? Linux, Windows or Apple……?

20. Mike says:

Thanks for posting man, very helpful.

21. Dinu says:

There is now a lower overhead module to profile PHP scripts: http://exteon.ro/en/products/php-tools/web3tracer

22. Satya says:

Hi,

We have a server side PHP script. Majorly, it interacts with MySQL Database (30+ tables) and performs some custom/business logic.

For various reasons, we need to run 100+ instances of this script as a cron process. So, any given point of time, there are 100+ cron jobs running.

We observe that ‘php’ is being placed always in the 1st 3 places in the output of ‘top’ command.

We want to profile/debug this script in real time (production server) when 100+ instances are running and find out the bottlenecks.

23. Dinu says:

Hi,
In reply to Satya and this article: we have built a PHP profiler on top of XHProf that also uses callgrind output format. The main advantage over XDebug is hugely lower overhead and better recursive function handling, as well as XHProf-style profiling begin and end functions, enabling automated unit testing. You can see it at http://www.exteon.ro/en/products/php-tools/web3tracer

24. Darek says:

Hi,

I have the same problem as Joseph Crawford. Could somebody give me any advice for solving this problem?

Any help will be greatly appreciated.

25. Tyler Style says:

Attn Joseph Crawford & Derek:
This is most likely because your webgrind output directory either doesn’t exist or doesn’t have the correct ownership/permissions.
Open up webgrind’s config.php and check what the storageDir is. Then check the ownership and permissions of that directory, and make sure your apache user (eg, www-data) can write to it.