Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Request-scoped performance profiler for PHP with microsecond-precision timing, memory tracking, percentile metrics, and intelligent threshold monitoring. Production-ready with sampling mode.

License

Notifications You must be signed in to change notification settings

MethorZ/php-profiler

Repository files navigation

PHP Profiler

CI codecov PHPStan PHP Version License

Request-scoped performance profiling library for PHP with detailed timing breakdowns, memory tracking, percentile metrics, and intelligent threshold monitoring.

Features

  • ⏱️ Precise Timing - Microsecond-precision operation timing with checkpoint support
  • 💾 Memory Profiling - Track current, peak, and delta memory usage
  • 📊 Percentile Metrics - P50, P75, P90, P95, P99 for statistical analysis
  • 📈 Comparative Analysis - Before/after comparisons for optimization measurement
  • 🎲 Sampling Mode - Reduce overhead with configurable sampling rates
  • ⚠️ Smart Thresholds - Configurable warnings for slow operations and high memory
  • 🔧 Context-Aware - Automatic configuration based on environment
  • 💿 Persistent Storage - Store metrics for later analysis
  • 🗄️ Query Analysis - MySQL EXPLAIN integration for slow queries
  • 🎯 Zero Production Overhead - Can be completely disabled
  • 🔌 Easy Integration - Simple trait for repository/service integration
  • 📝 Multiple Formats - Console-friendly and JSON output

Installation

composer require methorz/php-profiler

Quick Start

Basic Usage

use MethorZ\Profiler\OperationProfiler;

$profiler = OperationProfiler::start('database_query');

$profiler->checkpoint('prep');
$params = $this->prepareParams($data);

$profiler->checkpoint('exec');
$result = $this->executeQuery($query, $params);

$profiler->checkpoint('hydrate');
$objects = $this->hydrate($result);

$metrics = $profiler->end();

Repository Integration

use MethorZ\Profiler\Concern\ProfilesOperations;

class UserRepository
{
    use ProfilesOperations;

    public function fetchUsers(array $ids): array
    {
        $profiler = $this->startProfiling('fetch_users');

        try {
            $profiler->checkpoint('prep');
            $query = $this->buildQuery($ids);

            $profiler->checkpoint('exec');
            $result = $this->dal->execute($query);

            $profiler->checkpoint('hydrate');
            $users = $this->hydrate($result);

            $profiler->addCount('rows', count($users));
            return $users;
        } finally {
            $profiler->end();
        }
    }

    public function getLastQueryMetrics(): array
    {
        return $this->getLastProfilingMetrics();
    }
}

Advanced Features

1. Context-Aware Profiling

Automatically adjusts behavior based on environment:

use MethorZ\Profiler\ContextAwareProfiler;

// Auto-detects environment and configures appropriately
$profiler = ContextAwareProfiler::create();
$opProfiler = $profiler->start('operation');

// Production web: disabled
// Production CLI: 10% sampling
// Development: full profiling

2. Sampling Mode (Production Use)

Profile only a percentage of operations:

use MethorZ\Profiler\SamplingProfiler;

$sampler = new SamplingProfiler(0.1); // 10% sampling
$profiler = $sampler->start('high_traffic_operation');
// ... operation
$metrics = $profiler->end();

3. Percentile Metrics

Statistical analysis of operation performance:

use MethorZ\Profiler\MetricsCollector;

$collector = new MetricsCollector();

foreach ($batches as $batch) {
    $profiler = OperationProfiler::start('batch_process');
    // ... process batch
    $metrics = $profiler->end();
    $collector->record('batch_process', $metrics);
}

$aggregate = $collector->aggregate();
// Returns: ['percentiles' => ['p50' => 0.05, 'p95' => 0.15, 'p99' => 0.25, ...]]

4. Comparative Analysis

Measure optimization impact:

use MethorZ\Profiler\Analysis\MetricsComparator;
use MethorZ\Profiler\Storage\FileStorage;

$storage = new FileStorage('./metrics');

// Before optimization
$profiler = OperationProfiler::start('slow_query');
$result = $this->oldImplementation();
$before = $profiler->end();
$storage->store('before', $before);

// After optimization
$profiler = OperationProfiler::start('slow_query');
$result = $this->newImplementation();
$after = $profiler->end();

$comparator = new MetricsComparator();
$comparison = $comparator->compare($before, $after);

// Returns detailed comparison with improvement/regression detection
echo $comparison['summary']['messages'][0];
// "Performance improvement: 43.2% faster (0.5s → 0.284s)"

5. Persistent Storage

Store metrics for later analysis:

use MethorZ\Profiler\Storage\FileStorage;

$storage = new FileStorage('./profiling-data');

$profiler = OperationProfiler::start('operation');
// ... operation
$metrics = $profiler->end();

// Store metrics
$storage->store('optimization_v1', $metrics);

// Retrieve later
$historical = $storage->retrieve('optimization_v1');

6. MySQL Query Analysis

Automatic EXPLAIN for slow queries:

use MethorZ\Profiler\Database\MysqlQueryExplainer;

$explainer = new MysqlQueryExplainer($pdo);

$profiler = OperationProfiler::start('complex_query');
$result = $this->executeQuery($query);
$metrics = $profiler->end();

if ($metrics['total'] > 1.0) { // Slow query
    $explain = $explainer->explain($query);

    if ($explainer->needsOptimization($explain)) {
        $suggestions = $explainer->getSuggestions($explain);
        // ['Full table scan on "users" - consider adding an index']
    }
}

7. Performance Monitoring with Thresholds

Automatic warnings for performance issues:

use MethorZ\Profiler\PerformanceMonitor;

$monitor = PerformanceMonitor::create()
    ->setSlowOperationThreshold(1.0)    // 1 second
    ->setSlowPhaseThreshold(0.5)        // 500ms
    ->setHighMemoryThreshold(0.7)       // 70% of memory limit
    ->setHighRowCountThreshold(10000);  // 10k rows

$profiler = OperationProfiler::start('operation', $monitor);
// ... operation
$metrics = $profiler->end();

// Metrics include warnings if thresholds exceeded
if (isset($metrics['context']['warnings'])) {
    foreach ($metrics['context']['warnings'] as $warning) {
        error_log($warning);
    }
}

Output Formatting

Console Output

use MethorZ\Profiler\Formatter\ConsoleFormatter;

$formatter = new ConsoleFormatter();
echo $formatter->format($metrics);

Output:

Operation: fetch_users
Total: 125.50ms
Phases:
  prep:      3.20ms (2.5%)
  exec:    100.10ms (79.7%)
  hydrate:  22.20ms (17.7%)
Memory: 45.2MB (peak: 48.7MB, Δ+3.5MB)
Counts: ids: 150, rows: 2340

JSON Export

use MethorZ\Profiler\Formatter\JsonFormatter;

$formatter = new JsonFormatter(prettyPrint: true);
$json = $formatter->format($metrics);
file_put_contents('metrics.json', $json);

Configuration

Disable Profiling (Production)

// Disable globally (zero overhead)
OperationProfiler::setEnabled(false);

Environment-Based Configuration

// .env file
APP_ENV=production  // Auto-disables for web, samples for CLI

// Override in code
$profiler = ContextAwareProfiler::create()
    ->forceEnable()  // Force enabled regardless of environment
    ->forceSamplingRate(0.05);  // 5% sampling

Best Practices

✅ DO

  • Profile at repository/port layer for database operations
  • Use checkpoints to identify bottlenecks within operations
  • Aggregate metrics for batch operations
  • Use sampling mode in production
  • Store metrics for trend analysis
  • Compare before/after for optimization verification

❌ DON'T

  • Profile every method call (too much overhead)
  • Use for production monitoring without sampling (use proper APM tools)
  • Store metrics in database (they're request-scoped)
  • Profile trivial operations (<1ms)
  • Forget to disable in production web requests

Requirements

  • PHP 8.2 or higher
  • ext-json

Testing

# Run tests
composer test

# Run tests with coverage
composer test-coverage

# Run all quality checks
composer check

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details.

License

MIT License. See LICENSE for details.

Comparison to Other Tools

Feature php-profiler OpenTelemetry Prometheus StatsD
Purpose Dev profiling Distributed tracing Time-series metrics Real-time metrics
Overhead Medium (dev) Low (sampling) Low Very low
Memory tracking ✅ Yes ❌ No ❌ No ❌ No
Percentiles ✅ Yes ✅ Yes ✅ Yes ⚠️ Limited
Sub-operations ✅ Checkpoints ✅ Spans ⚠️ Manual ⚠️ Manual
Comparison ✅ Built-in ❌ No ❌ No ❌ No
Production ⚠️ Sampling only ✅ Yes ✅ Yes ✅ Yes
Setup ✅ Simple ⚠️ Medium ✅ Simple ✅ Simple

Use php-profiler for: Development profiling, optimization measurement, debugging performance issues

Use OpenTelemetry/Prometheus for: Production monitoring, distributed tracing, long-term metrics storage

Credits

Created by Thorsten Merz

Links

About

Request-scoped performance profiler for PHP with microsecond-precision timing, memory tracking, percentile metrics, and intelligent threshold monitoring. Production-ready with sampling mode.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Sponsor this project

Packages

No packages published

Languages