Skip to content
Search

Benchmarks

Flow ships a local benchmark suite built on phpbench. It runs real DataFrame pipelines over pregenerated datasets so you can measure the performance impact of a change and compare branches or extension on/off on identical data.

Requirements

Benchmarks must be run inside nix-shell so opcache, the profiler and (optionally) the flow_php extension are available and the environment is reproducible.

nix-shell

The phpbench binary lives in its own tool directory (installed by composer install):

tools/phpbench/vendor/bin/phpbench

Running

just benchmark forwards every argument to phpbench run (like just test does for phpunit) and defaults to --report=flow-report (pass your own --report=... to override). Bare just benchmark runs every suite.

# run every suite and print the custom Flow report
just benchmark

The flow-report columns are: benchmark, subject, set, mem_peak, mode, total_time, rstdev. The set column is the parameter set label - the row count and, for the parquet/floe format benchmarks, the engine variant (e.g. 100,000,php vs 100,000,arrow).

Defaults (see phpbench.json.dist): remote executor (per-iteration process isolation, the only executor that measures mem_peak), revs=1 (one e2e pipeline is one measurement), iterations=3, warmup=1, opcache.enable_cli=1, pcov.enabled=0, unlimited memory_limit.

Row-count

Each suite runs a single row-count tier, 100,000 by default. Set FLOW_BENCH_ROWS to an integer to run at that count instead (datasets are generated on demand and cached, so any count works):

FLOW_BENCH_ROWS=1000000 just benchmark

Tags and baseline comparison

Store a run under a tag, then compare a later run against it:

# store a baseline
just benchmark --store --tag=before

# ... make your change ...

# run the current code and compare it against the stored baseline
just benchmark --ref=before

To report a stored run without re-running (e.g. phpbench report, phpbench log), call the binary directly: tools/phpbench/vendor/bin/phpbench report --ref=before --report=flow-report.

Stored runs live in var/phpbench/ (gitignored).

Profiling a scenario without phpbench

Every benchmark is a thin phpbench wrapper (benchmarks/suites/) around a plain, phpbench-free scenario class (benchmarks/src/, namespace Flow\Benchmarks\). A scenario is invokable directly, so you can profile it with Blackfire without any phpbench overhead. Bootstrapping through benchmarks/bootstrap.php mirrors the phpbench environment (wipes var/, exports the service defaults) so the profile matches the benchmark run:

blackfire run php -r 'require "benchmarks/bootstrap.php"; (new Flow\Benchmarks\Joining\JoinOrdersWithSellersScenario(Flow\ETL\Join\Join::left, 100000))->run();'

Found a typo or an outdated section? Edit this page on GitHub


Contributors

Built in the open.

Join us on GitHub
scroll back to top