Repository navigation
perf: skip redundant work in RouteCollection::create() - #10656
Merged
Merged
Conversation
…eate()`
Run the placeholder `str_ireplace` loop only when the route key contains
`:`, and call `helper('array')` only on the first `create()` per
collection. The route table output is unchanged.
Route table build, PHP 8.3, OPcache on, median of 7 runs:
100 routes 203 -> 168 µs, 1000 routes 2044 -> 1680 µs (~18%).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
michalsn
reviewed
Oct 23, 2026
michalsn
left a comment
Member
There was a problem hiding this comment.
Looks good to me - I also ran benchmarks locally and saw similar improvements.
Could we add a changelog entry under “Changes”? Something like this would work:
- Router: Reduced route registration overhead in
RouteCollection::create()by skipping placeholder replacement for route keys without:and callinghelper('array')only once per collection.
Member
Author
|
Oh, yeah, completely forgot the change log. Incoming. |
neznaika0
approved these changes
Oct 24, 2026
ddevsr
approved these changes
Oct 24, 2026
michalsn
reviewed
Oct 24, 2026
Co-authored-by: Michal Sniatala <michal@sniatala.pl>
michalsn
approved these changes
Oct 24, 2026
paulbalandan
approved these changes
Oct 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #10617
Without route caching, the route table is rebuilt on every request. This PR removes two pieces of mostly wasted work from
RouteCollection::create(), which runs once per registered route:str_ireplace(':' . $tag, ...)loop now runs only when the route key contains:. Every placeholder search string starts with:, so a key without one cannot match. The output is identical.helper('array'): this is now called only on the firstcreate()of each collection, using a private flag.RouteCollectionno longer uses the helper, but the helper still loads at the same point as before, so apps that rely on that side effect keep working.There are no public or protected API changes, and the route table is unchanged (same keys, handlers, names and options).
Benchmark
Time to build the route table on
4.8: PHP 8.3.23 CLI on macOS, OPcache on, production mode, a newRouteCollectionper build. The routes are a realistic mix: a third static, a third with one placeholder, a third with two, in groups of 10. Before and after were run alternately for 4 rounds. Each round takes the median of 7 timed runs, and the table shows the median across rounds.Comparing the fastest round on each side gives similar savings (14–19%). The same benchmark on
developshowed 17–19% savings (2.05 → 1.69 µs per route).The issue estimated about 40%, but that assumed every route skips the placeholder loop. In this mix only the static third does, so the expected saving is about 0.5 µs × ⅓ + 0.24 µs ≈ 0.41 µs per route, which is close to the 0.4–0.5 µs measured. Apps with mostly static routes will save more.
Benchmark script
Run it from the repo root with
php -d opcache.enable_cli=1 bench_routes.php.Tests
New tests in
RouteCollectionTestlock in current behavior. All three pass both before and after the change:(?:...), mixed with built-in placeholders, still expands correctly.(:NUM),:segment). The:guard relies on this behavior.No changelog or user guide entry is included, as planned in the issue.
Checklist:
🤖 Generated with Claude Code