How to Use DDEV XHProf for PHP Performance Profiling: A Complete Guide
DDEV provides built-in XHProf support through the ddev xhprof command, which automatically configures the PHP extension, injects profiling collectors via auto_prepend_file, and stores run data in your project directory for analysis.
DDEV ships with native support for the XHProf profiling extension, enabling detailed function-level performance analysis for PHP applications without manual configuration. By leveraging the ddev xhprof project command and container-aware architecture, developers can capture, store, and analyze profiling data consistently across local, CI, and staging environments.
How DDEV XHProf Integration Works
DDEV implements XHProf as a project-level command suite that handles extension loading, web server configuration, and data collection automatically. The architecture consists of several coordinated components:
- Global configuration flag – Managed in
pkg/globalconfig/xhprof_mode.go, this flag tracks whether XHProf mode is active across projects. - Project command wrapper – Implemented in
pkg/ddevapp/xhprof_xhgui.go, theddev xhprofcommand toggles the extension, manages thexhprof_prepend.phpinjector, and restarts containers. - PHP extension loading – Version-specific INI files (e.g.,
containers/ddev-php-base/ddev-php-files/etc/php/8.2/mods-available/xhprof.ini) load thexhprof.soextension when enabled. - Request instrumentation – The
containers/ddev-webserver/ddev-webserver-base-files/usr/local/bin/xhprof/xhprof_prepend.phpscript prepends to every request viaauto_prepend_file, starting the profiler at request initiation and writing raw data to disk. - Web server exposure – Nginx configuration in
containers/ddev-webserver/ddev-webserver-base-files/etc/nginx/common.d/xhprof.confexposes the profiling directory and disables caching for accurate measurement. - Helper scripts – Low-level enable/disable scripts in
containers/ddev-webserver/ddev-webserver-base-files/usr/local/bin/(e.g.,enable_xhprof) handle container-level extension toggling.
When active, XHProf writes run files (xhprof_*.raw) to your project's .ddev/xhprof/ directory, making data version-controllable and shareable between team members.
Enabling XHProf for Your Project
To start profiling, enable the XHProf mode for your current DDEV project. This command updates the global configuration, copies the xhprof directory structure into your project, and restarts the web container to load the PHP extension.
ddev xhprof enable
The command modifies .ddev/global_config.yaml through the logic in pkg/globalconfig/xhprof_mode.go, then executes the enable scripts that configure the PHP auto_prepend_file directive. Once enabled, every PHP request (web or CLI) automatically triggers data collection.
Collecting Profiling Data
Profiling Web Requests
After enabling XHProf, simply visit any page of your application through the browser:
# The site is now profiling every request
open https://myproject.ddev.site
Each request generates a raw profiling file in .ddev/xhprof/. The xhprof_prepend.php script handles initialization and cleanup automatically, ensuring the run file is written to disk when the request completes.
Profiling CLI Scripts
For command-line PHP execution, use the ddev xhprof run wrapper to execute a script while capturing performance data:
ddev xhprof run php -d memory_limit=2G scripts/heavy_task.php
This command runs your script with the XHProf extension active and outputs the location of the generated raw file (e.g., .ddev/xhprof/xhprof_5f8c3a2e9d3b4.raw).
Direct Container Execution
Alternatively, execute PHP commands inside the container while the extension is enabled:
ddev exec php -r 'include "index.php";'
Analyzing Profiling Results
Raw File Inspection
List and inspect the generated profiling runs directly:
ls .ddev/xhprof/*.raw
These raw files contain serialized XHProf data that can be processed by analysis tools or viewed with the xhprof_html interface if installed locally.
Visualizing with XHGui
For graphical analysis, point an XHGui instance at your profiling directory. Mount the DDEV xhprof folder into a Dockerized XHGui container:
docker run -d \
-v $(pwd)/.ddev/xhprof:/tmp/xhprof \
-p 8080:80 xhgui/xhgui
Access http://localhost:8080 to browse call graphs, inclusive/exclusive function costs, and flame charts. XHGui reads the raw files directly from the mounted directory.
Key Configuration Files
Understanding the source implementation helps troubleshoot edge cases:
| File | Purpose |
|---|---|
pkg/ddevapp/xhprof_xhgui.go |
Contains the main command logic for ddev xhprof enable, disable, and run subcommands. |
pkg/globalconfig/xhprof_mode.go |
Handles persistence of the XHProf enabled state in global configuration. |
containers/ddev-php-base/ddev-php-files/etc/php/8.2/mods-available/xhprof.ini |
PHP 8.2 extension configuration; similar files exist for other supported versions. |
containers/ddev-webserver/ddev-webserver-base-files/usr/local/bin/enable_xhprof |
Shell script executed inside the container to activate the extension and prepend file. |
containers/ddev-webserver/ddev-webserver-base-files/usr/local/bin/xhprof/xhprof_prepend.php |
The PHP script injected at the start of every request to manage profiling lifecycle. |
containers/ddev-webserver/ddev-webserver-base-files/etc/nginx/common.d/xhprof.conf |
Nginx rules exposing the .ddev/xhprof directory via the web server. |
pkg/ddevapp/xhprof_xhgui_test.go |
Automated test suite verifying correct directory creation and extension toggling. |
Disabling XHProf
When profiling is complete, disable the extension to eliminate performance overhead:
ddev xhprof disable
This removes the auto_prepend_file directive, stops further profiling, and cleans up the temporary configuration. Optionally, clear old run files:
rm -rf .ddev/xhprof/*
Summary
- Zero-configuration setup – The
ddev xhprofcommand handles extension installation, PHP ini configuration, and web server rules automatically. - Container-native storage – Profiling data resides in
.ddev/xhprof/, making it environment-consistent and version-control friendly. - Dual-mode profiling – Supports both web requests (via
auto_prepend_file) and CLI scripts (viaddev xhprof run). - XHGui compatible – Raw output files work with standard visualization tools for call graphs and flame charts.
- Clean teardown – The
ddev xhprof disablecommand reverses all changes without manual file editing.
Frequently Asked Questions
How do I enable XHProf profiling in DDEV?
Run ddev xhprof enable in your project directory. This command updates the global configuration through pkg/globalconfig/xhprof_mode.go, restarts your web container, and activates the PHP extension via the helper scripts in containers/ddev-webserver/ddev-webserver-base-files/usr/local/bin/.
Where does DDEV store XHProf profiling data?
DDEV writes raw profiling files to the .ddev/xhprof/ directory inside your project root. The xhprof_prepend.php script generates files named xhprof_*.raw containing serialized performance data for each request.
Can I profile CLI scripts with DDEV XHProf?
Yes. Use the ddev xhprof run command followed by your script execution. This wrapper ensures the XHProf extension is active during the command's lifecycle and reports the output file location upon completion.
Does enabling XHProf affect production deployments?
No. DDEV XHProf is a local development feature controlled by the xhprof_mode flag in your global configuration. The extension and auto_prepend_file directives only exist within DDEV containers and do not modify your production codebase or configurations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →