perf: skip redundant work in `RouteCollection::create()` during route registration
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 62/100
- Tipo de issue
- Refactorización
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Stack tecnológico
- php
- Área
- backend, performance
Línea de trabajo
The work is in RouteCollection::create() in system/Router/RouteCollection.php. Read the placeholder str_ireplace loop and the helper('array') call there, then check how RouterTest.php and RouteCollectionTest.php in tests/system/Router/ exercise route keys. Done means the placeholder loop runs only when the key contains :, the array helper loads once per collection with the same side effect, and the existing route tables and the two new cases still pass.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Problem
Without route caching, the route table is rebuilt on every request. Each $routes->get() (or post(), add(), and so on) runs RouteCollection::create(), which costs about 1.9 µs per route. That's about 8 times more than the worst-case cost of matching a route.
Two steps in create() do work that is usually wasted:
- The placeholder loop.
create()runsstr_ireplace(':' . $tag, ...)once for every registered placeholder (6 by default), even when$fromhas no:and nothing can match. That costs about 0.50 µs per route. helper('array'). It's called on everycreate().RouteCollectionno longer uses any array-helper function, but the call still loads the helper for the app as a side effect. Repeat calls cost about 0.24 µs per route.
Measurements
PHP 8.3 on macOS, OPcache on, production mode, warm. Config construction cost was turned off to approximate the state after #10615. The routes are a realistic mix: a third static, a third with one placeholder, a third with two, spread across groups.
| Routes | Build route table | Match last route | 404 |
|---|---|---|---|
| 30 | 78 µs | 15 µs | 11 µs |
| 100 | 248 µs | 32 µs | 27 µs |
| 300 | 608 µs | 85 µs | 79 µs |
| 1000 | 2,030 µs | 263 µs | 252 µs |
Here's the cost breakdown of one $routes->get() call:
| Step | Cost |
|---|---|
esc(strip_tags($from)) |
0.49 µs |
Placeholder str_ireplace loop (6 placeholders) |
0.50 µs |
helper('array') |
0.24 µs |
| Everything else | ~0.6 µs |
| Total | ~1.87 µs |
Proposal
- In
create(), run the placeholder loop only when the route key contains:. If it has no:, nostr_ireplacecan match, and no replacement can add a:. So the output is identical. That includes custom placeholders whose patterns contain:, such as(?:...). - Call
helper('array')only on the firstcreate()of each collection, using a private flag. The helper still loads at the same point as today, so apps that quietly depend on it keep working. A short comment will explain that the call stays only for this side effect.
Estimated savings are about 0.74 µs per route, roughly 40% of the build cost:
- 100 routes: about 75 µs per request
- 1000 routes: about 0.75 ms per request
Compatibility
- No change to public or protected APIs. The only new state is private.
- The route table comes out the same: same keys, handlers, names, and options.
- No changelog or upgrade-guide entry is planned.
Not changing
esc()stays increate(). Apps can replaceesc()inapp/Common.php, so skipping the call would quietly bypass a custom version on route paths. A fasteresc()for thehtmlcontext could be a separate issue.- The matcher (
Router::checkRoutes()). A FastRoute-style matcher was prototyped. Without route caching, building its lookup structure on each request cost about as much as the linear scan it replaced. So the net gain was small at typical route counts.
Tests
Add cases to tests/system/Router/RouteCollectionTest.php that lock in today's behavior:
- A route with no placeholders keeps its exact key.
- A custom placeholder whose pattern contains
(?:...), mixed with built-in placeholders, still expands correctly.
Run RouteCollectionTest.php and RouterTest.php.
Related
- #10615: config construction cost
- #10616: filter discovery cost
- Lenguaje dominante
- PHP
- Estrellas
- 6k
- Forks
- 2k
- Merge medio
- 1 d 22 h
- PR fusionados (30 d)
- 59
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de codeigniter4/CodeIgniter4
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
codeigniter4/CodeIgniter4#10616 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
codeigniter4/CodeIgniter4#10618 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 25/100
codeigniter4/CodeIgniter4#10615 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
codeigniter4/CodeIgniter4#10589 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
dev
Dificultad 5/5 Más de una semana Aptitud para principiantes 25/100
codeigniter4/CodeIgniter4#10427 · 5 comentarios ·
Los mantenedores suelen responder en 1 día
Todos los issues de codeigniter4/CodeIgniter4
Issues similares
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
-
L: java:gradle L: java:maven L: ruby:bundler T: bug 🐞
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
dependabot/dependabot-core#16547 ·
Los mantenedores suelen responder en 1 día
-
cloning objets from planningAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
glpi-project/glpi#25922 ·
Los mantenedores suelen responder en 1 día
-
Bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
Automattic/safe-publish#726 ·
Los mantenedores suelen responder en 1 día
-
[Translation][TwigBridge][TwigBundle] Add `HtmlTranslator` and the `tra…Posiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. AbiertoTranslation TwigBridge
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
symfony/symfony-docs#23308 ·
Los mantenedores suelen responder en 3 días