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.

Webgrind Interface

Installation

Before using webgrind, you must first install Xdebug.

Installing webgrind is pretty simple:

  1. Download webgrind
  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!

Comments

18 Responses to “Profiling PHP with Xdebug and Webgrind”

  1. Philip Morton on January 21st, 2009 5:08 am

    Thanks for the clear explanation.

  2. Diglin on January 22nd, 2009 5:04 am

    Here are the lines to add in your php.ini after the loading xdebug line:

    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 on January 22nd, 2009 10:49 am

    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 on January 27th, 2009 8:55 am

    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 on January 27th, 2009 9:27 am

    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 on January 27th, 2009 10:15 am

    @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!

  7. ask on February 24th, 2009 5:47 am

    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. aaaaaaaaaaaaaaaaaaaa on March 26th, 2009 8:07 am

    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 on March 26th, 2009 9:45 am

    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 on March 27th, 2009 10:48 pm

    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 on March 28th, 2009 8:41 am

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

  12. Ben Rexin on June 15th, 2009 4:42 pm

    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. Installing Webgrind, the Xdebug Profiler « Madhusanka’s Tech Blog on October 26th, 2009 5:33 am

    [...] (Yeah, the installation is no that easy). I had Xdebug already installed, and after going through this, I managed get it running, after following these [...]

  14. Housing on November 25th, 2009 8:10 pm

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

  15. Joseph Crawford on March 9th, 2010 10:26 am

    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

  16. Bart McLeod on June 16th, 2010 3:34 am

    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

  17. alexandrov on July 29th, 2010 4:34 pm

    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.

  18. Sarah Walsh on August 10th, 2010 6:54 am

    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

Got something to say?