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