Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Benchmark Laravel Package

janiaje/benchmark

A lightweight benchmarking toolkit for Laravel and PHP applications. Measure execution time, compare code snippets, and profile performance with a simple, expressive API. Includes helpers for timing closures, database queries, and custom benchmarks, plus formatted reports to help you spot bottleneck...

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer:

composer require janiaje/laravel-benchmark --dev

The package registers itself via Laravel auto-discovery, so there is no config file to publish for basic use. Import the facade and wrap the code you want to time:

use Janiaje\Benchmark\Facades\Benchmark;

Benchmark::dd(fn () => User::with('posts')->get());

dd() measures the closure, dumps the elapsed time, and stops execution — the fastest way to answer "how long does this actually take?" from php artisan tinker or a throwaway route. Check the README's facade class in vendor/janiaje/laravel-benchmark/src before your first run: the API is a handful of static helpers (measure, dump, dd, and a repeat-style each), and method names are the whole surface area, so a two-minute read covers it.

The first realistic use case is a suspected N+1 query or a slow accessor during local development. Don't install it to micro-optimize; install it to get a number instead of a hunch.

Implementation Patterns

Compare two implementations side by side. This is where the package earns its keep:

Benchmark::dump(fn () => User::with('posts')->get());
Benchmark::dump(fn () => User::all()->load('posts'));

Two lines in tinker and you have a defensible answer for a code review.

Repeat for stability. A single measurement is noise on a shared dev machine. Use the repeat helper to run the same closure N times and read the average:

Benchmark::each(100, fn () => $service->calculate($payload));

Benchmark inside a test. Wrap a hot path in a Pest test so you notice when a refactor makes it three times slower. Keep the assertion loose (an order-of-magnitude ceiling, not a millisecond), or it will fail on CI hardware.

Probe one layer at a time. Measure the query, then the collection transformation, then the serialization separately. A single number around a controller method tells you nothing about which of the three is the problem.

Wrap the hot path, not the boot. Time the specific call — a scope, a cast, a formatter — rather than Route::dispatch(). Framework boot dwarfs your code and drowns the signal.

Use it as a scratch endpoint. A routes/web.php entry guarded by app()->isLocal() that dumps a few measurements is quicker than juggling tinker sessions when you're iterating on a query shape.

Gotchas and Tips

  • Maintenance risk is real. Sixteen stars, no dependents, last release September 2023. Treat it as a ~100-line convenience wrapper, not infrastructure. If you adopt it widely, copy the benchmark logic into your own Support/Benchmark.php and drop the dependency — you lose nothing.
  • Beware --dev drift. Install it as a dev dependency. If it sneaks into production require, add a guard or you'll ship benchmarking code on live requests.
  • The repeat helper multiplies side effects. Benchmark::each(100, fn () => User::create([...])) inserts 100 rows. Wrap writes in a transaction you roll back, or benchmark read-only paths only.
  • Warm up first. The first invocation pays for autoloading, query-plan caching, and opcache misses. Discard the first run, or call the closure once before measuring.
  • Dev numbers aren't prod numbers. Xdebug, no opcache, and a cold cache can make a 5 ms query look like 80 ms. Use the package to find relative differences, not to promise absolute latencies.
  • dd() in a queued job kills the worker. It is exit under the hood. Reach for dump() (or log the output) anywhere that isn't an interactive session.
  • Missing facade after install? Run php artisan package:discover or clear the cached manifest — auto-discovery only registers on a fresh boot.
  • It measures wall time, not memory. If you're chasing an OOM or a fat serialized payload, pair it with memory_get_peak_usage() or reach for Telescope/Debugbar, which give you the query log and timeline the package doesn't.
  • Extension point is essentially nil. There's no driver abstraction or output formatter to hook into. If you need custom reporting (statsd, a CI threshold, an assertion helper), you're writing it yourself around the returned duration.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package