Install the Bundle
composer require jns/xhprof-bundle
Add to config/bundles.php:
return [
// ...
Jns\XhprofBundle\JnsXhprofBundle::class => ['all' => true],
];
Enable XHProf Extension
Ensure the xhprof PHP extension is installed and enabled in php.ini:
extension=xhprof.so
Basic Configuration
Add to config/packages/jns_xhprof.yaml:
jns_xhprof:
enabled: true
output_dir: '%kernel.project_dir%/var/log/xhprof'
ignore_functions: ['ignore_me']
First Use Case
Trigger profiling via the Symfony profiler toolbar (appears automatically in dev environment) or manually in code:
use Jns\XhprofBundle\Xhprof;
$profiler = new Xhprof();
$profiler->start('my_custom_profile_name');
// Code to profile...
$profiler->stop();
Web Profiling
$profiler->start('user_auth_flow');
$user = $this->authService->authenticate($request);
$profiler->stop();
# config/routes.yaml
app_profile_route:
path: /profile-heavy-task
controller: App\Controller\HeavyController::index
methods: GET
xhprof: true # Enable XHProf for this route only
Console Command Profiling
use Jns\XhprofBundle\Xhprof;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class MyCommand extends Command {
protected function execute(InputInterface $input, OutputInterface $output) {
$profiler = new Xhprof();
$profiler->start('console_import');
// Command logic...
$profiler->stop();
$output->writeln('Profiling data saved to: ' . $profiler->getOutputDir());
}
}
Conditional Profiling Use environment variables or config flags to toggle profiling:
# config/packages/dev/jns_xhprof.yaml
jns_xhprof:
enabled: '%env(bool:XHPROF_ENABLED)%'
$profiler->start('event_dispatcher');
$this->eventDispatcher->dispatch($event);
$profiler->stop();
$profiler->start('db_queries');
$entity = $entityManager->find(Entity::class, $id);
$profiler->stop();
$profiler->addMetadata(['user_id' => $user->id, 'action' => 'update_profile']);
Performance Overhead
# config/packages/prod/jns_xhprof.yaml
jns_xhprof:
enabled: false
Output Directory Permissions
Ensure var/log/xhprof is writable:
mkdir -p var/log/xhprof
chmod -R 775 var/log/xhprof
Default path: %kernel.project_dir%/var/log/xhprof.
Ignored Functions Exclude vendor or internal functions to reduce noise:
jns_xhprof:
ignore_functions:
- 'Symfony\\'
- 'Doctrine\\'
- 'Illuminate\\'
Console Command Quirks
find var/log/xhprof -type f -mtime +7 -delete
Memory Limits XHProf can consume significant memory for long-running processes. Monitor with:
$profiler->setMemoryLimit(500); // MB
Missing Toolbar Tab:
enabled: true in config.xhprof extension is loaded (php -m | grep xhprof).php bin/console cache:clear.Empty Profiles:
start()/stop() are called around the code to profile.ignore_functions isn’t filtering out critical calls.Corrupted Data:
var/log/xhprof and retry. Files are auto-generated with timestamps.Custom Profiler Classes
Extend Jns\XhprofBundle\Xhprof to add logic:
class CustomProfiler extends Xhprof {
public function startWithMetadata($name, array $metadata) {
$this->addMetadata($metadata);
parent::start($name);
}
}
Post-Processing Hooks
Override getOutputDir() or generateReport() to customize output format (e.g., JSON for APIs):
$profiler->setOutputFormat('json');
Integration with Blackfire Use XHProf for broad profiling and Blackfire for deep dives (complementary tools).
Symfony Flex Recipes Although the bundle is archived, you can manually create a recipe for auto-configuration in modern Symfony apps:
# config/recipes/jns_xhprof.yaml
jns_xhprof:
enabled: '%kernel.debug%'
output_dir: '%kernel.project_dir%/var/log/xhprof'
How can I help you explore Laravel packages today?