[How2Tips] How to benchmark your code with xdebug
Reading time : 1 min
Dr Klein shares with you his thoughts about how to profile your php scripts, in a post extracted from our internal knowledge database.
Before we start, let’s just be aware that there are many ways to profile your apps :
- xhprof (by Facebook, almost dead)
- FriendsOfPHP/uprofiler (renamed fork of xhprof, by Sensio, almost dead, prototype for blackfire)
- xhmem (dead)
- blackfire (Saas)
- https://tideways.io/ (the php extension generates the same output as xhprof)
We’ll focus on xdebug for now. Always think of what you’re trying to achieve : in this case you are trying to isolate a performance bottleneck.
It’s thus a good idea to isolate the portion of code you’re trying to benchmark in a separate script. This way you’ll be able to run it via the CLI, which simplifies greatly the setup. Isolate your subject under test (SUT) : imagine you want to profile a Symfony service.
Just create a simple php script :
(bin/test.php): <?php require __DIR__.'/../vendor/autoload.php'; use App\Symfony\AppKernel; $kernel = new AppKernel('dev', false); $kernel->boot(); $container = $kernel->getContainer(); $container->get('expensive_service')->run(); // whatever
Activate the xdebug profiler
The easiest is to punctually enable it via php -d :
php -dxdebug.profiler_enable=1 -dxdebug.profiler_output_dir=$(pwd) bin/test.php
Note: this will activate the profiler for this process only, and will put the cachegrind output in the current folder.
Once you generated a cachegrind file, just run it with kcachegrind <cachegrind.out.whatever>.
It will help you understand where php took most of its time.
It also generates nice call graphs.
Running with docker?
First, grasp the basics.
Don’t forget that containers are just UNIX processes. Nothing magical. If you don’t get UNIX processes, switch to Windows. Now that we’re on the same page, remember that the container has a different filesystem tree than your host one. In order to access the cachegrind files generated by xdebug, you’ll have to mount a volume, like in the following example:
docker exec -v $(pwd):/xdebug my_image php -dxdebug.profiler_enable=1 -dxdebug.profiler_output_dir=/xdebug /xdebug/bin/test.php
This will ask docker to mount your current folder as /xdebug, and it will dump the cachegrind files in it.
But we diverge, because that has nothing to do with xdebug.
Always verify if xdebug is correctly configured:
On your host:
php -i | grep profiler_enable
Or with docker:
docker exec my_image php -i | grep profiler_enable
It should display :
xdebug.profiler_enable => On => On
Any questions ? Ping us at @KNPLabs