PHPackages                             dragon-code/runtime-comparison - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. dragon-code/runtime-comparison

Abandoned → [dragon-code/benchmark](/?search=dragon-code%2Fbenchmark)Library[Utility &amp; Helpers](/categories/utility)

dragon-code/runtime-comparison
==============================

Simple comparison of code execution speed between different options

v1.5.1(3y ago)7203MITPHPPHP ^8.1CI passing

Since Feb 3Pushed 2mo ago3 watchersCompare

[ Source](https://github.com/TheDragonCode/runtime-comparison)[ Packagist](https://packagist.org/packages/dragon-code/runtime-comparison)[ Fund](https://boosty.to/dragon-code)[ GitHub Sponsors](https://github.com/sponsors/TheDragonCode)[ RSS](/packages/dragon-code-runtime-comparison/feed)WikiDiscussions main Synced today

READMEChangelog (10)Dependencies (3)Versions (13)Used By (0)

Benchmark
=========

[](#benchmark)

  ![Benchmark](https://camo.githubusercontent.com/2790c2c6f1264c2789845423bec6ca245f663ffabee86a016384695a67a880fd/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f42656e63686d61726b2e706e673f7061747465726e3d746f706f677261706879267374796c653d7374796c655f3226666f6e7453697a653d3130307078266d643d312673686f7757617465726d61726b3d31267468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b726571756972652b2d2d646576267061636b6167654e616d653d647261676f6e2d636f646525324662656e63686d61726b266465736372697074696f6e3d53696d706c652b636f6d70617269736f6e2b6f662b636f64652b657865637574696f6e2b73706565642b6265747765656e2b646966666572656e742b6f7074696f6e7326696d616765733d68747470732533412532462532467777772e7068702e6e6574253246696d616765732532466c6f676f732532466e65772d7068702d6c6f676f2e737667)[![Stable Version](https://camo.githubusercontent.com/19d600c23341c6e1e865fe13d21d51e060e92a3bf66c0b76a02d557eea03195d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f546865447261676f6e436f64652f62656e63686d61726b3f6c6162656c3d737461626c65267374796c653d666c61742d737175617265)](https://packagist.org/packages/dragon-code/benchmark)[![Total Downloads](https://camo.githubusercontent.com/7dd21e1305830f33f9c60339bb9f9d2362d235ae8c977eeade44fc1d8ce6e181/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f647261676f6e2d636f64652f62656e63686d61726b2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/dragon-code/benchmark)[![Github Workflow Status](https://camo.githubusercontent.com/04cdb0ea4a8eb30ebda6849de480524cd31d5345668990a2ca9e915a04fcc479/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f546865447261676f6e436f64652f62656e63686d61726b2f74657374732e796d6c3f7374796c653d666c61742d737175617265)](https://github.com/TheDragonCode/benchmark/actions)[![License](https://camo.githubusercontent.com/3cc7bbc4bb0c0838f406e07a96244aad325fed626887c7fafc02255fa131edaa/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f647261676f6e2d636f64652f62656e63686d61726b2e7376673f7374796c653d666c61742d737175617265)](LICENSE)

Installation
------------

[](#installation)

```
composer require dragon-code/benchmark --dev
```

Usage
-----

[](#usage)

Note

When more than 9 iterations are used, the top and bottom 10% of results are excluded from the average calculation, producing cleaner data less dependent on external factors.

```
use function DragonCode\Benchmark\bench;

bench()
    ->compare(
        foo: fn () => /* some code */,
        bar: fn () => /* some code */,
    )
    ->toConsole();
```

You can use both the `bench()` helper function and the `Benchmark` class (`new Benchmark()` or `Benchmark::make()`).

Callbacks can be passed as an array or as arguments, with or without named keys:

```
use DragonCode\Benchmark\Benchmark;

// As named arguments
new Benchmark()->compare(
    foo: fn () => /* some code */,
    bar: fn () => /* some code */,
)->toConsole();

// As an associative array
bench()->compare([
    'foo' => fn () => /* some code */,
    'bar' => fn () => /* some code */,
])->toConsole();
```

Example output:

```
+-------+-------------------------+-------------------------+
| #     | foo                     | bar                     |
+-------+-------------------------+-------------------------+
| min   | 14.3472 ms - 0 bytes    | 14.3657 ms - 0 bytes    |
| max   | 15.7684 ms - 0 bytes    | 15.7249 ms - 0 bytes    |
| avg   | 15.0967475 ms - 0 bytes | 14.9846725 ms - 0 bytes |
| total | 1207.7398 ms - 0 bytes  | 1198.7738 ms - 0 bytes  |
+-------+-------------------------+-------------------------+
| order | 2                       | 1                       |
+-------+-------------------------+-------------------------+
```

### Iterations Count

[](#iterations-count)

By default, the benchmark performs 100 iterations per callback. Use the `iterations` method to change this. The current iteration number is available as a callback parameter:

```
use DragonCode\Benchmark\Benchmark;

new Benchmark()
    ->iterations(5)
    ->compare(
        foo: fn (int $iteration) => /* some code */,
        bar: fn (int $iteration) => /* some code */,
    )
    ->toConsole();
```

### Warm-up

[](#warm-up)

Use the `warmup` method to run each callback a few times before the measured iterations. Warm-up runs behave identically to regular ones (`beforeEach` / `afterEach` are invoked, the progress bar advances), but their time and memory are not included in the final statistics.

This stabilizes results by absorbing one-time costs such as cold caches, JIT/opcache priming and lazy autoloading.

Disabled by default.

```
use DragonCode\Benchmark\Benchmark;

new Benchmark()
    ->warmup(3) // run 3 warm-up iterations per callback before measuring
    ->compare(
        foo: fn () => /* some code */,
        bar: fn () => /* some code */,
    );
```

### Round Precision

[](#round-precision)

Use the `round` method to set the number of decimal places in console output:

```
new Benchmark()
    ->round(2)
    ->compare(
        foo: fn () => /* some code */,
        bar: fn () => /* some code */,
    )
    ->toConsole();
```

```
+-------+----------------------+----------------------+
| #     | foo                  | bar                  |
+-------+----------------------+----------------------+
| min   | 14.58 ms - 0 bytes   | 14.38 ms - 0 bytes   |
| max   | 15.55 ms - 0 bytes   | 15.71 ms - 0 bytes   |
| avg   | 15.01 ms - 0 bytes   | 15.1 ms - 0 bytes    |
| total | 1201.09 ms - 0 bytes | 1207.76 ms - 0 bytes |
+-------+----------------------+----------------------+
| order | 1                    | 2                    |
+-------+----------------------+----------------------+
```

### Deviation Values

[](#deviation-values)

Use the `deviations` method to measure the deviation between results. All loops will repeat the specified number of times, and the output will include a `deviation` row:

```
new Benchmark()
    ->deviations(4)
    ->compare(
        foo: fn () => /* some code */,
        bar: fn () => /* some code */,
    )
    ->toConsole();
```

```
+------------------+----------------------+-----------------------+
| #                | foo                  | bar                   |
+------------------+----------------------+-----------------------+
| min              | 0.0011 ms - 0 bytes  | 0.0009 ms - 0 bytes   |
| max              | 0.0111 ms - 0 bytes  | 0.0082 ms - 0 bytes   |
| avg              | 0.00453 ms - 0 bytes | 0.002715 ms - 0 bytes |
| total            | 0.0906 ms - 0 bytes  | 0.0543 ms - 0 bytes   |
+------------------+----------------------+-----------------------+
| order            | 2                    | 1                     |
+------------------+----------------------+-----------------------+
| deviation time   | +0.002768            | +0.000919             |
| deviation memory | 0                    | 0                     |
+------------------+----------------------+-----------------------+
```

### Callbacks

[](#callbacks)

You can register callbacks to run before/after the entire benchmark loop or before/after each iteration:

```
use DragonCode\Benchmark\Benchmark;

new Benchmark()
    ->before(fn (int|string $name) => /* once before all iterations of a callback */)
    ->beforeEach(fn (int|string $name, int $iteration) => /* before each iteration */)
    ->after(fn (int|string $name) => /* once after all iterations of a callback */)
    ->afterEach(fn (int|string $name, int $iteration) => /* after each iteration */)
    ->compare(
        fn () => /* some code */,
        fn () => /* some code */,
    )
    ->toConsole();
```

The result of `beforeEach` is passed to the compare callback:

```
new Benchmark()
    ->beforeEach(fn (int|string $name, int $iteration) => /* prepare data */)
    ->compare(
        fn (mixed $before) => /* use $before */,
        fn (mixed $before) => /* use $before */,
    )
    ->toConsole();
```

### Results

[](#results)

#### toConsole

[](#toconsole)

Outputs results to the console:

```
new Benchmark()
    ->round(2)
    ->compare(
        foo: static fn () => /* some code */,
        bar: static fn () => /* some code */,
    )
    ->toConsole();
```

```
+-------+----------------------+----------------------+
| #     | foo                  | bar                  |
+-------+----------------------+----------------------+
| min   | 14.68 ms - 0 bytes   | 14.56 ms - 0 bytes   |
| max   | 15.69 ms - 0 bytes   | 15.64 ms - 0 bytes   |
| avg   | 15.13 ms - 0 bytes   | 15.07 ms - 0 bytes   |
| total | 1210.38 ms - 0 bytes | 1205.26 ms - 0 bytes |
+-------+----------------------+----------------------+
| order | 2                    | 1                     |
+-------+----------------------+----------------------+
```

With deviation values:

```
+------------------+-----------------------+---------------------+
| #                | foo                   | bar                 |
+------------------+-----------------------+---------------------+
| min              | 15.68 ms - 202 bytes  | 2.35 ms - 102 bytes |
| max              | 112.79 ms - 209 bytes | 9.76 ms - 109 bytes |
| avg              | 53.03 ms - 205 bytes  | 5.94 ms - 105 bytes |
| total            | 1696.81 ms - 6.42 KB  | 190.17 ms - 3.30 KB |
+------------------+-----------------------+---------------------+
| order            | 2                     | 1                   |
+------------------+-----------------------+---------------------+
| deviation time   | +0.100715             | +0.114023           |
| deviation memory | 0                     | 0                   |
+------------------+-----------------------+---------------------+
```

#### toData

[](#todata)

Returns results as an array of `DragonCode\Benchmark\Data\ResultData` DTO objects:

```
return new Benchmark()
    ->deviations()
    ->compare(
        foo: fn () => /* some code */,
        bar: fn () => /* some code */,
    )
    ->toData();
```

```
array:2 [
  "foo" => DragonCode\Benchmark\Data\ResultData {#23
    +min: DragonCode\Benchmark\Data\MetricData {#64
      +time: 0.001
      +memory: 0.0
    }
    +max: DragonCode\Benchmark\Data\MetricData {#65
      +time: 0.0036
      +memory: 0.0
    }
    +avg: DragonCode\Benchmark\Data\MetricData {#66
      +time: 0.0024209375
      +memory: 0.0
    }
    +total: DragonCode\Benchmark\Data\MetricData {#67
      +time: 0.7747
      +memory: 0.0
    }
    +deviation: DragonCode\Benchmark\Data\DeviationData {#68
      +percent: DragonCode\Benchmark\Data\MetricData {#69
        +time: 0.0007048383984778
        +memory: 0.0
      }
    }
  }
  "bar" => DragonCode\Benchmark\Data\ResultData {#70
    +min: DragonCode\Benchmark\Data\MetricData {#71
      +time: 0.001
      +memory: 0.0
    }
    +max: DragonCode\Benchmark\Data\MetricData {#72
      +time: 0.0032
      +memory: 0.0
    }
    +avg: DragonCode\Benchmark\Data\MetricData {#73
      +time: 0.00242875
      +memory: 0.0
    }
    +total: DragonCode\Benchmark\Data\MetricData {#74
      +time: 0.7772
      +memory: 0.0
    }
    +deviation: DragonCode\Benchmark\Data\DeviationData {#75
      +percent: DragonCode\Benchmark\Data\MetricData {#76
        +time: 0.00061642429076895
        +memory: 0.0
      }
    }
  }
]
```

#### toAssert

[](#toassert)

Validates benchmark results against expected thresholds. Both `from` and `till` parameters are optional — use one or both:

```
use DragonCode\Benchmark\Benchmark;

new Benchmark()
    ->compare(/* ... */)
    ->toAssert()

    ->toBeMinTime(from: 0.5, till: 3)       // between 0.5 and 3 ms
    ->toBeMaxTime(from: 0.5, till: 3)       // between 0.5 and 3 ms
    ->toBeAvgTime(from: 0.5, till: 3)       // between 0.5 and 3 ms
    ->toBeTotalTime(from: 0.5, till: 9)     // between 0.5 and 9 ms

    ->toBeMinMemory(from: 0, till: 1024)    // between 0 and 1024 bytes
    ->toBeMaxMemory(from: 0, till: 1024)    // between 0 and 1024 bytes
    ->toBeAvgMemory(from: 0, till: 1024)    // between 0 and 1024 bytes
    ->toBeTotalMemory(from: 0, till: 4096)  // between 0 and 4096 bytes

    ->toBeDeviationTime(from: -0.5, till: 0.5)   // deviation between -0.5% and 0.5%
    ->toBeDeviationMemory(from: -2.5, till: 2.5); // deviation between -2.5% and 2.5%
```

### Regression Testing

[](#regression-testing)

Detects performance regressions by comparing current results to a saved baseline (snapshot).

#### How To Work

[](#how-to-work)

- **First run:** no `.snap` files exist — results are written to disk, no check is performed.
- **Next runs:** results are compared to the snapshot; exceeding `$max` percent throws an `AssertionError`.
- **Location:** snapshots are stored per call site (subdirectory derived from the caller file and line).

Note

Delete the corresponding `.snap` files to reset the baseline — the next run will recreate them.

#### Configuring the Snapshot Directory

[](#configuring-the-snapshot-directory)

Set the snapshot directory via `snapshots()`. Default: `./.benchmarks`.

```
use DragonCode\Benchmark\Benchmark;

new Benchmark()
    ->snapshots(directory: __DIR__ . '/.benchmarks')
    // ...
    ->toAssert()
    ->toBeRegressionTime(max: 10)
    ->toBeRegressionMemory(max: 10);
```

Tip

Commit the generated snapshot files to version control to keep regression checks consistent across environments and CI.

#### toBeRegressionTime

[](#toberegressiontime)

Fails if execution time exceeds the snapshot by more than `$max` percent.

```
use DragonCode\Benchmark\Benchmark;

new Benchmark()
    // ...
    ->toAssert()
    ->toBeRegressionTime(max: 15); // allow up to 15% time regression
```

#### toBeRegressionMemory

[](#toberegressionmemory)

Fails if memory usage exceeds the snapshot by more than `$max` percent.

```
use DragonCode\Benchmark\Benchmark;

new Benchmark()
    // ...
    ->toAssert()
    ->toBeRegressionMemory(max: 15); // allow up to 15% memory regression
```

### Disable Progress Bar

[](#disable-progress-bar)

```
use DragonCode\Benchmark\Benchmark;

new Benchmark()
    ->disableProgressBar()
    // ...
```

License
-------

[](#license)

This package is licensed under the [MIT License](LICENSE).

###  Health Score

39

↓

LowBetter than 84% of packages

Maintenance58

Moderate activity, may be stable

Popularity13

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor1

Top contributor holds 88.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

12

Last Release

1244d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/b77790e612f1c9beed1e1533e36eba4954fbd6da2a5c9f71e845cd0f5465f0ad?d=identicon)[Helldar](/maintainers/Helldar)

---

Top Contributors

[![andrey-helldar](https://avatars.githubusercontent.com/u/10347617?v=4)](https://github.com/andrey-helldar "andrey-helldar (359 commits)")[![actions-user](https://avatars.githubusercontent.com/u/65916846?v=4)](https://github.com/actions-user "actions-user (20 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (16 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (7 commits)")[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (3 commits)")[![roxblnfk](https://avatars.githubusercontent.com/u/4152481?v=4)](https://github.com/roxblnfk "roxblnfk (1 commits)")

---

Tags

benchmarkcomparatorcomparatorscomparisoncomparison-toolruntimespeedspeedtesttimetimercomparatortimetimercomparisonruntimespeedcomparatorsspeedtestcomparison-tool

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/dragon-code-runtime-comparison/health.svg)

```
[![Health](https://phpackages.com/badges/dragon-code-runtime-comparison/health.svg)](https://phpackages.com/packages/dragon-code-runtime-comparison)
```

###  Alternatives

[dragon-code/benchmark

Simple comparison of code execution speed between different options

12037.9k6](/packages/dragon-code-benchmark)[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[friendsoftypo3/content-blocks

TYPO3 CMS Content Blocks - Content Types API | Define reusable components via YAML

103519.9k53](/packages/friendsoftypo3-content-blocks)[phel-lang/phel-lang

Phel is a functional programming language that compiles to PHP

5186.0k18](/packages/phel-lang-phel-lang)[dagger/dagger

Dagger PHP SDK

261.1k](/packages/dagger-dagger)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
