ZetCode

PHP hrtime Function

last modified May 18, 2025

The hrtime function in PHP provides high-resolution timing measurements, returning the system's high-resolution time in nanoseconds. Introduced in PHP 7.3, it's ideal for precise benchmarking and performance measurement where microtime may not provide sufficient accuracy.

The hrtime function in PHP provides high-resolution timing with nanosecond precision, returning either a total nanosecond count as an integer or an array containing seconds and nanoseconds. It is monotonic, meaning it is unaffected by system time changes, making it ideal for performance benchmarking, profiling, and execution time optimization. To improve measurement accuracy, small operations should be tested with multiple iterations, while accounting for overhead to ensure precise results. For better readability, values can be converted into commonly used units, such as milliseconds or seconds.

hrtime([ bool $get_as_number ]): mixed

The hrtime function has an optional $get_as_number parameter. If set to true, the function returns the current time in nanoseconds as an integer. If set to false or omitted, it returns an array with two elements: seconds and nanoseconds.

Key features of hrtime:

Basic usage of hrtime

hrtime can be called in two ways: without parameters to get the current time, or with a boolean parameter to get time as an array. By default it returns nanoseconds as an integer.

basic_usage.php
<?php 

declare(strict_types=1);

// Get current time in nanoseconds
$time = hrtime(true);
echo "Current time: $time nanoseconds\n";

// Get time as an array [seconds, nanoseconds]
$timeArray = hrtime();
print_r($timeArray);

// Measure time difference
$start = hrtime(true);
usleep(1000); // Sleep for 1000 microseconds (1ms)
$end = hrtime(true);

$duration = $end - $start;
echo "Slept for: " . ($duration / 1e6) . " milliseconds\n";

This demonstrates basic hrtime usage. The first call gets the current time in nanoseconds as an integer. The second call without parameters returns an array with seconds and nanoseconds. The example also shows how to measure the duration of a code section by calculating the difference between two hrtime(true) calls.

λ php basic_usage.php
Current time: 3846251417975 nanoseconds
Array
(
    [0] => 3846
    [1] => 251417975
)
Slept for: 1.067367 milliseconds

Comparing hrtime with microtime

hrtime provides several advantages over microtime for precise timing measurements. This example compares both functions.

comparison.php
<?php 

declare(strict_types=1);

// Using microtime()
$startMicro = microtime(true);
usleep(100);
$endMicro = microtime(true);
$microDuration = ($endMicro - $startMicro) * 1e6; // Convert to microseconds

// Using hrtime()
$startHr = hrtime(true);
usleep(100);
$endHr = hrtime(true);
$hrDuration = ($endHr - $startHr) / 1e3; // Convert to microseconds

echo "microtime measured: $microDuration microseconds\n";
echo "hrtime measured: $hrDuration microseconds\n";

// Measure resolution
$iterations = 1000;
$times = [];

for ($i = 0; $i < $iterations; $i++) {

    $start = hrtime(true);
    $end = hrtime(true);
    $times[] = $end - $start;
}

echo "Minimum resolution: " . min($times) . " nanoseconds\n";
echo "Average resolution: " . array_sum($times)/$iterations . " nanoseconds\n";

This shows that hrtime typically provides higher resolution timing than microtime. The resolution test demonstrates hrtime can measure very short intervals that microtime might not accurately capture.

λ php comparison.php
microtime measured: 16182.18421936 microseconds
hrtime measured: 803.9 microseconds
Minimum resolution: 0 nanoseconds
Average resolution: 63.9 nanoseconds

Benchmarking with hrtime

hrtime is ideal for benchmarking code sections. Here's how to properly structure benchmarks and calculate meaningful statistics.

benchmarking.php
<?php 

declare(strict_types=1);

function benchmark(callable $function, int $iterations = 1000): array
{
    $durations = [];
    
    // Warm-up (run once to avoid initialization bias)
    $function();
    
    for ($i = 0; $i < $iterations; $i++) {
        $start = hrtime(true);
        $function();
        $end = hrtime(true);
        $durations[] = $end - $start;
    }
    
    $total = array_sum($durations);
    
    return [
        'iterations' => $iterations,
        'total_ns' => $total,
        'avg_ns' => $total / $iterations,
        'min_ns' => min($durations),
        'max_ns' => max($durations),
        'variance' => stats_variance($durations),
    ];
}

function stats_variance(array $values): float
{
    $avg = array_sum($values) / count($values);
    $sum = 0;
    foreach ($values as $value) {
        $sum += ($value - $avg) ** 2;
    }
    return $sum / count($values);
}

// Example benchmark
$result = benchmark(function() {
    // Code to benchmark
    $array = range(1, 1000);
    $sum = array_sum($array);
}, 10000);

echo "Benchmark Results:\n";
echo "Iterations: {$result['iterations']}\n";
echo "Total time: " . ($result['total_ns'] / 1e9) . " seconds\n";
echo "Average: " . ($result['avg_ns'] / 1e6) . " ms\n";
echo "Min: {$result['min_ns']} ns\n";
echo "Max: {$result['max_ns']} ns\n";
echo "Variance: {$result['variance']}\n";

This demonstrates a robust benchmarking approach using hrtime. The benchmark function runs the code multiple times, calculates statistics, and includes a warm-up run to account for initialization costs. Variance helps identify how consistent the timings are.

λ php benchmarking.php
Benchmark Results:
Iterations: 10000
Total time: 0.070156 seconds
Average: 0.0070156 ms
Min: 6300 ns
Max: 63800 ns
Variance: 4937010.6400005

Measuring function execution time

hrtime can precisely measure how long functions take to execute. Here's a reusable function to time any callable.

function_timing.php
<?php 

declare(strict_types=1);

function measure(callable $function, ...$args): array
{
    $start = hrtime(true);
    $result = $function(...$args);
    $end = hrtime(true);
    
    return [
        'result' => $result,
        'time_ns' => $end - $start,
    ];
}

// Example usage
function calculatePrimes(int $limit): array
{
    $primes = [];

    for ($i = 2; $i <= $limit; $i++) {

        $isPrime = true;
        for ($j = 2; $j <= sqrt($i); $j++) {
            if ($i % $j === 0) {
                $isPrime = false;
                break;
            }
        }

        if ($isPrime) {
            $primes[] = $i;
        }
    }

    return $primes;
}

$measurement = measure('calculatePrimes', 1000);
echo "Found " . count($measurement['result']) . " primes\n";
echo "Took " . ($measurement['time_ns'] / 1e6) . " milliseconds\n";

This shows how to wrap any function call with precise timing using hrtime. The measure function returns both the result and the time taken, allowing you to analyze performance without affecting the function's operation.

λ php function_timing.php
Found 168 primes
Took 0.3902 milliseconds

Real-world profiling example

Here's how to use hrtime to profile different implementations of an algorithm to determine which is more efficient.

profiling.php
<?php 

declare(strict_types=1);

// Two implementations of Fibonacci sequence
function fibRecursive(int $n): int
{
    if ($n <= 1) return $n;
    return fibRecursive($n - 1) + fibRecursive($n - 2);
}

function fibIterative(int $n): int
{
    if ($n <= 1) return $n;
    
    $a = 0;
    $b = 1;
    
    for ($i = 2; $i <= $n; $i++) {
        $c = $a + $b;
        $a = $b;
        $b = $c;
    }
    
    return $b;
}

// Profile both implementations
function profile(string $name, callable $function, int $input): array
{
    $start = hrtime(true);
    $result = $function($input);
    $end = hrtime(true);
    
    return [
        'name' => $name,
        'result' => $result,
        'time_ns' => $end - $start,
    ];
}

$input = 30; // Warning: recursive gets very slow with larger numbers

$recursive = profile('Recursive', 'fibRecursive', $input);
$iterative = profile('Iterative', 'fibIterative', $input);

echo "Fibonacci($input) results:\n";
echo "{$recursive['name']}: {$recursive['result']} in " . 
     ($recursive['time_ns'] / 1e6) . " ms\n";
echo "{$iterative['name']}: {$iterative['result']} in " . 
     ($iterative['time_ns'] / 1e6) . " ms\n";

This example clearly shows the performance difference between recursive and iterative implementations of the Fibonacci sequence, with hrtime providing precise measurements of the time difference.

λ php profiling.php
Fibonacci(30) results:
Recursive: 832040 in 124.234367 ms
Iterative: 832040 in 0.005367 ms

Best practices

To get accurate and meaningful results with hrtime, follow these best practices:

best_practices.php
<?php 

declare(strict_types=1);

// 1. Always measure multiple iterations for small operations
function measureMany(callable $function, int $iterations = 1000): float
{
    $start = hrtime(true);
    for ($i = 0; $i < $iterations; $i++) {
        $function();
    }

    $end = hrtime(true);
    return ($end - $start) / $iterations;
}

// 2. Account for the measurement overhead
$start = hrtime(true);
$end = hrtime(true);
$overhead = $end - $start;
echo "Measurement overhead: $overhead ns\n";

// 3. Use monotonic time for reliable measurements
// hrtime() is monotonic by default (unlike microtime())

// 4. Convert units appropriately for readability
function formatDuration(int $ns): string
{
    if ($ns < 1e3) return "$ns ns";
    if ($ns < 1e6) return round($ns/1e3, 2) . " μs";
    if ($ns < 1e9) return round($ns/1e6, 2) . " ms";
    return round($ns/1e9, 2) . " s";
}

// 5. Run warm-up iterations before measuring
function warmup(callable $function, int $iterations = 10): void
{
    for ($i = 0; $i < $iterations; $i++) {
        $function();
    }
}

// 6. Consider using a benchmarking library for complex scenarios
// Example: https://github.com/phpbench/phpbench

// 7. Document your measurement methodology
/**
 * Measures database query performance
 * @param callable $query Should execute and return the query result
 * @param int $iterations Number of times to run for stable measurement
 * @return array Contains 'result', 'time_ns', and 'iterations'
 */
function measureQuery(callable $query, int $iterations = 100): array
{
    warmup($query);
    
    $start = hrtime(true);
    $result = null;
    for ($i = 0; $i < $iterations; $i++) {
        $result = $query();
    }
    $end = hrtime(true);
    
    return [
        'result' => $result,
        'time_ns' => ($end - $start) / $iterations,
        'iterations' => $iterations
    ];
}

These practices help ensure your timing measurements are accurate, reliable, and meaningful. The key points are to measure multiple iterations, account for overhead, and properly document your methodology.

In this article we have covered the basics of using hrtime in PHP, including how to measure execution time, compare it with microtime, and use it for benchmarking. We also discussed best practices for accurate measurements and profiling real-world scenarios.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all PHP tutorials.