Skip to content

Profiler

Ray Fung edited this page Feb 26, 2026 · 3 revisions

Profiler

Razy includes a lightweight runtime performance profiler that captures memory, CPU, and timing snapshots at labeled checkpoints. Use it to identify bottlenecks, track memory growth, and measure execution time across code sections.


Table of Contents


Quick Start

use Razy\Profiler;

$profiler = new Profiler(); // captures initial baseline

// ... do some work ...
$profiler->checkpoint('db_query');

// ... more work ...
$profiler->checkpoint('template_render');

// ... final work ...
$profiler->checkpoint('response_sent');

// Compare consecutive checkpoints
$report = $profiler->report();
print_r($report);

Creating Checkpoints

Each checkpoint captures a snapshot of the runtime state at that moment:

$profiler = new Profiler();

// Add labeled checkpoints at key points
$profiler->checkpoint('boot');
$profiler->checkpoint('routes_loaded');
$profiler->checkpoint('controller_executed');
$profiler->checkpoint('view_rendered');
$profiler->checkpoint('response_sent');

Rules:

  • Labels must be non-empty strings
  • Labels must be unique (throws on duplicates)
  • The constructor captures an initial __init checkpoint automatically

Generating Reports

report() ??Consecutive Comparisons

Compare consecutive checkpoints to see deltas between each step:

// Compare all consecutive pairs
$report = $profiler->report();
// [
//   'boot ??routes_loaded' => [
//     'execution_time' => 0.0042,
//     'memory_usage'   => 524288,
//     ...
//   ],
//   'routes_loaded ??controller_executed' => [
//     'execution_time' => 0.0156,
//     ...
//   ],
// ]

// Compare specific checkpoints only
$report = $profiler->report(false, 'boot', 'controller_executed', 'response_sent');

// Compare each checkpoint against __init (total from start)
$report = $profiler->report(compareWithInit: true);
// [
//   '__init ??boot' => [...],
//   '__init ??routes_loaded' => [...],
//   '__init ??controller_executed' => [...],
// ]

reportTo() ??Single Comparison

Compare a specific checkpoint against the initial baseline:

$delta = $profiler->reportTo('controller_executed');
// [
//   'execution_time'   => 0.0198,    // seconds since __init
//   'memory_usage'     => 1048576,   // bytes change
//   'memory_allocated' => 2097152,   // bytes change
//   'output_buffer'    => 0,         // bytes change
//   'user_mode_time'   => 0.015,     // CPU seconds
//   'system_mode_time' => 0.003,     // CPU seconds
//   'defined_functions' => ['myFunc1', 'myFunc2'],  // new functions
//   'declared_classes'  => ['App\\MyController'],    // new classes
// ]

Captured Metrics

Each checkpoint captures the following data:

Metric Type Source Description
memory_usage int memory_get_usage() Heap memory in bytes
memory_allocated int memory_get_usage(true) System-allocated memory in bytes
output_buffer int ob_get_length() Output buffer size
user_mode_time float getrusage() User CPU seconds
system_mode_time float getrusage() System CPU seconds
execution_time float microtime(true) Wall-clock time in seconds
defined_functions array get_defined_functions() User-defined function names
declared_classes array get_declared_classes() Declared class names

How Reports Compute Deltas

  • Numeric metrics (memory, time): arithmetic difference (checkpoint - baseline)
  • Array metrics (functions, classes): array_diff(checkpoint, baseline) ??shows new entries only

Use Cases

Measuring Database Query Time

$profiler = new Profiler();
$profiler->checkpoint('before_query');

$result = $db->query('SELECT * FROM users WHERE active = 1');

$profiler->checkpoint('after_query');
$delta = $profiler->reportTo('after_query');
echo "Query took: " . round($delta['execution_time'] * 1000, 2) . "ms\n";
echo "Memory delta: " . number_format($delta['memory_usage']) . " bytes\n";

Profiling an Entire Request

$profiler = new Profiler();

// Phase 1: Bootstrap
require 'bootstrap.php';
$profiler->checkpoint('bootstrap');

// Phase 2: Routing
$route = $router->match($request);
$profiler->checkpoint('routing');

// Phase 3: Controller
$response = $route->execute();
$profiler->checkpoint('controller');

// Phase 4: Rendering
echo $response->render();
$profiler->checkpoint('render');

// Full report
$report = $profiler->report(compareWithInit: true);
foreach ($report as $label => $metrics) {
    printf(
        "%s: %.2fms, %s memory\n",
        $label,
        $metrics['execution_time'] * 1000,
        number_format($metrics['memory_usage'])
    );
}

Detecting Class Table Bloat (Worker Mode)

$profiler = new Profiler();
$profiler->checkpoint('request_start');

// ... handle request ...

$profiler->checkpoint('request_end');
$delta = $profiler->reportTo('request_end');

if (count($delta['declared_classes']) > 50) {
    error_log('Warning: ' . count($delta['declared_classes']) . ' new classes loaded this request');
}

API Reference

Method Signature Description
__construct () Create profiler with initial __init checkpoint
checkpoint (string $label): Profiler Capture snapshot (throws on empty/duplicate)
report (bool $compareWithInit = false, string ...$labels): array Consecutive delta report
reportTo (string $label): array Compare checkpoint to __init

??Previous: RateLimiter FTP-SFTP

Clone this wiki locally