Skip to content
Muhammet Şafak
tr

Laravel's preload curve: 123 files buy eight times what the last 1,912 do

How far can a curated preload take Laravel, and what does each slice cost in start-up time?

Finding

The curve is not proportional to volume. The first 1,592 files — Laravel's own framework — buy 30 ms and add 1.2 seconds to start-up. The next 1,094 Symfony files buy 9.5 ms for free. The **123 files** after that (psr, carbon) buy 15.7 ms, more than the 1,094 before them. And the last 1,912 buy 1.8 ms while adding another 1.2 seconds. So the blanket preload the earlier record measured as a ceiling is the worst point on the curve that is not the origin: stopping at 2,809 files gives 12.77 ms for 1,514 ms of start-up, while 4,721 files ask 2,691 ms to reach 10.96 ms.

Sweet spot: 2,809 files
12.77 ms −81%
Its start-up cost
+1,132 ms
What the 123-file slice buys
15.7 ms
What the last 1,912 buy
1.8 ms

Method

The same images, the same PHP 8.4 build and the same measurement point as the opcache record — the first request a container ever serves. Curation is a **path filter** over Composer's classmap rather than a hand-picked list of classes: a hand-picked list cannot be reproduced, a filter can. The five variants nest deliberately (framework ⊂ +symfony ⊂ +psr/carbon ⊂ everything) so the curve reads as "add this much more" rather than as four unrelated points. Fresh container per variant, three repeats, median. Preload runs in php-fpm's master process, so its cost is measured as the time until the container answers with a 200; that window includes nginx's own start-up but is the same constant across all five variants.

High confidence Repeated runs, controlled environment, raw data published.
Measured on

measured yesterday

Published

Environment

PHP
8.4.24 NTS · opcache on · JIT off
Application
Laravel, production install, classmap-authoritative
Variants
path filter over the classmap · five nested slices
Repeats
3 · median reported
Hardware
Apple M4 Pro · 12 cores · Docker Desktop 29.7.2 · aarch64

Technologies

PHP opcache Laravel Composer Docker nginx

To reproduce

REPEATS=3 ./bench/preload-curate.sh

The opcache measurement left Laravel between two points: no preload file of its own, a cold first request of 76 ms, and a blanket classmap preload that reaches 14 ms while adding 2.3 seconds to php-fpm’s start-up. That record measured the blanket version as a ceiling. This one draws the curve between the two — and shows the ceiling is a bad place to stand.

The curve

Cold first request against the number of files preloaded

The five variants nest: each point adds a slice to the one before it. The horizontal axis is files compiled.

ms lower is better Source: bench/preload-curate.sh, median of three repeats

Data table
bench/preload-curate.sh, median of three repeats
Series 01,5922,6862,8094,721
cold first request 68.37 ms38.01 ms28.48 ms12.77 ms10.96 ms

The chart is drawn in the browser; the table below carries the same data.

Slice Compiled Cold request fpm ready Marginal gain Marginal cost
no preload 0 68.37 ms 382 ms
laravel/framework 1,592 38.01 ms 1,553 ms −30.4 ms +1,171 ms
+ symfony 2,686 28.48 ms 1,538 ms −9.5 ms free
+ psr, carbon the sweet spot 2,809 12.77 ms 1,514 ms −15.7 ms free
everything 4,721 10.96 ms 2,691 ms −1.8 ms +1,177 ms
Marginal columns are against the row above. “Free” means the start-up difference sits inside measurement noise.

Not how many, which ones

The curve’s shape is not proportional to volume, and that is the finding.

123 files buy eight times what the last 1,912 do. The psr and carbon slice adds 123 files and takes the cold request from 28.48 ms to 12.77 ms. The 1,912 files after it take only 1.8 ms.

The reason is date handling: Laravel’s first request pulls on Carbon’s loading chain, and that chain is deeply linked — without preloading it gets resolved again on every cold start. A framework being “heavy” is not about how many files it has; it is about which tree the first request walks.

”Compile everything” is the worst choice

The earlier record measured the blanket classmap as an optimistic upper bound. The curve shows it differently: 4,721 files buy 1.8 ms over 2,809 and cost 1,177 ms of start-up. The last slice charges 654 milliseconds of start-up for every millisecond it saves.

For a service deploying ten times a day that is twelve seconds of added start-up in exchange for 1.8 ms for the first visitor. Even on steady traffic the trade is weak.

It does not catch Symfony

Symfony reaches 2.50 ms with its own official file. Laravel’s best point here is 10.96 ms — four times behind, and that is with everything preloaded.

The difference is structural. Symfony’s preload file is generated from its compiled container, so resolving the service definitions has already happened at build time. Laravel’s container resolves at runtime, and preload does not remove that work — it only removes class compilation. Preload saves you from compiling PHP source; it does not save you from the application’s own set-up.

The file Laravel does not ship

What this leaves is not a number but a file: a preload generated with the filter ^/vendor/(laravel\/framework|symfony|psr|nesbot|carbon)/, giving 12.77 ms at 1.5 seconds of start-up — the thing the framework itself does not publish. The generator is in the repository and runs against any Laravel application.

Related posts

Share:

Other records

All records

opcache preload cuts the deploy bill by up to fourteen times — but five of seven frameworks do not hand it to you

With `opcache.preload` on, how long is the first request seven PHP frameworks serve after a deploy, what does the gain cost, and who can actually have it?

Finding

Preload shortens the cold first request by between 3.5× and 14.2×: Symfony drops from 35.58 ms to 2.50 ms, down to Phalcon's bare figure. But only two of the seven candidates — Symfony and CodeIgniter — publish a preload file of their own; for the other five the gain sits on the table waiting for the user to write one. Writing one is not as easy as it looks: a preload generated blindly from the classmap never brings Symfony up at all, and on CodeIgniter it does worse (5.29 ms) than the hand-picked official file (3.13 ms). And the cost does not vanish: Laravel's classmap preload takes the 62 ms it saves each visitor and writes it back as 2,340 ms of php-fpm start-up.

measured yesterday

High confidence

The PHP ecosystem does not wait for a new release — but it does not declare support either

After a PHP release ships, when do the 500 most-installed Composer packages declare that they support it, and how much does that declaration actually say?

Finding

43.5% of installs arrive on a constraint with no upper bound at all — `symfony/console` says `>=8.4.1` today, which claims support for PHP 12 as well. Of the 280 packages that do close the top, 247 made the commitment before the version existed: `guzzlehttp/guzzle` covered 8.4 in October 2020, four years early. That leaves 33 packages that genuinely waited, at a median of 325 days. The raw medians fall version over version and read as an ecosystem speeding up; restricted to an equal observation window the trend reverses (238 → 215 → 325 days).

checked yesterday

High confidence

The fixed cost of installing a PHP framework: disk size tells you nothing

How many megabytes on disk, how many files per request and how many milliseconds on the first request do seven PHP frameworks cost — and which of those numbers actually predicts throughput under load?

Finding

Disk size predicts nothing: Yii2 has the largest vendor tree at 34.1 MB and loads only 62 files per request, among the fewest in the field. Files per request predicts nothing either: CodeIgniter loads 96 files and serves 6,431 req/s, Symfony loads 224 and serves 13,067. The one number that genuinely separates them is the first request served with a cold opcache: 2.2 ms for Phalcon, 72.2 ms for Laravel — thirty-three times. That is the compile bill the first visitor pays after every deploy, and it is measured in tens of milliseconds, not kilobytes.

measured 3 days ago

High confidence

Search the site

Start typing to search posts, projects and pages.

Esc to close Powered by Pagefind