perftools/php-profiler
A low-overhead PHP profiler extension plus client library for collecting and exporting performance data. Capture CPU and memory usage for scripts and web requests, then send profiles to compatible backends for analysis and visualization.
Installation
composer require perftools/php-profiler
Add the XHProf extension to your PHP installation (requires pecl install xhprof).
First Use Case Enable profiling in a Laravel controller or middleware:
use PerfTools\Profiler;
public function index()
{
Profiler::start('my_controller_action');
// Your logic here...
Profiler::stop();
return view('results', ['data' => Profiler::getData()]);
}
Viewing Results Use the included XHGUI viewer (included in the package) to visualize the data:
php vendor/bin/xhgui
Access http://localhost:8080 to see the profiling results.
Middleware Integration Wrap profiling logic in middleware for automatic instrumentation:
public function handle($request, Closure $next)
{
Profiler::start('request_' . $request->path());
$response = $next($request);
Profiler::stop();
return $response;
}
Service-Level Profiling Profile critical services (e.g., repositories, jobs):
public function fetchData()
{
Profiler::start('UserRepository::fetchActiveUsers');
$users = User::where('active', true)->get();
Profiler::stop();
return $users;
}
Conditional Profiling Enable profiling only in development/staging:
if (app()->environment(['local', 'staging'])) {
Profiler::start('critical_path');
// ...
Profiler::stop();
}
Custom Metrics Track custom events (e.g., database queries, API calls):
Profiler::start('DB::query', 'SELECT * FROM users');
DB::select('SELECT * FROM users');
Profiler::stop();
handle():
public function handle()
{
Profiler::start('SendEmailJob');
// Job logic...
Profiler::stop();
}
return response()->json([
'data' => $result,
'profiling' => Profiler::getData()
]);
Memory Overhead Profiling adds ~10-20% overhead. Disable in production:
if (app()->environment('production')) {
Profiler::disable();
}
XHProf Extension
xdebug). Disable XDebug if using both:
xdebug.mode=off
Data Retention
XHGUI stores data in runtime/xhprof. Clear old files periodically:
rm -rf runtime/xhprof/*
Nested Profiling
Avoid deeply nested start/stop calls—it bloats the call graph. Use parent-child relationships:
Profiler::start('parent');
Profiler::start('child');
// ...
Profiler::stop(); // Stops 'child' and closes 'parent'
php -m | grep xhprof).Profiler::start('query', 'SQL_HERE') to isolate DB bottlenecks.Custom Data Collectors
Extend PerfTools\Profiler\Collector\BaseCollector to add metrics (e.g., Redis calls):
class RedisCollector extends BaseCollector {
public function collect() {
return ['cache_hits' => Redis::get('hits')];
}
}
Hooks
Use Laravel’s booted event to auto-start profiling:
public function boot()
{
if (app()->environment('local')) {
Profiler::start('app_boot');
}
}
Storage Backends
Replace XHGUI with a custom storage (e.g., database) by implementing PerfTools\Profiler\Storage\StorageInterface.
How can I help you explore Laravel packages today?