perf: filter discovery tokenizes the app and system `Config/Filters.php` on every request
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 72/100
- Tipo de issue
- Refactorización
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- php
- Área
- backend, performance
Línea de trabajo
Empieza en el método privado discoverFilters(), que se llama desde el constructor de Filters, y revisa cómo se pasan los resultados de FileLocator::search() a getClassname(). Añade una comprobación que omita las rutas APPPATH y SYSTEMPATH Config/Filters.php antes de esa llamada, dejando las demás rutas sin cambios. Ejecuta tests/system/Filters/FiltersTest.php; está terminado cuando un locator espía mediante Services::injectMock('locator', ...) no muestre ninguna llamada a getClassname() para los archivos de la aplicación o del sistema, y el filtro personalizado de tests/_support y su alias test-customfilter sigan funcionando.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Problem
Filters::__construct() calls the deprecated discoverFilters() on every request when filter discovery is on, which it is by default. That method finds every Config/Filters.php across all namespaces. For each file, it calls FileLocator::getClassname(), which runs file_get_contents() and token_get_all() on the file.
In a default app, discovery finds only two files:
app/Config/Filters.phpsystem/Config/Filters.php
Both get read and tokenized, and then both are skipped, because their class is Config\Filters or CodeIgniter\Config\Filters. So every request pays to parse two files it never uses.
Measurements
PHP 8.3 on macOS, OPcache on, production mode, warm. Each number is averaged over 300 runs.
| Case | Time |
|---|---|
new Filters(...), discovery on (default) |
~103 µs |
new Filters(...), discovery off |
~0.2 µs |
FileLocator::search('Config/Filters.php') |
~15 µs |
FileLocator::getClassname() per file |
~42 µs |
For a full request to a bare closure route, Services::filters() is about 126 µs. That's the largest single cost left once #10615 lands, at about 14–18% of the request.
Proposal
In discoverFilters(), compare each found path against APPPATH . 'Config/Filters.php' and SYSTEMPATH . 'Config/Filters.php' before calling getClassname(). Skip those two paths with no file read.
FileLocator::search()already returns real paths, andAPPPATHandSYSTEMPATHare real paths too, so a plain string compare works.- Every other file keeps today's class-name check, unchanged. Module and package discovery files are still included as they are now.
With the default setup, the cost drops to the search() call alone, about 15 µs.
Compatibility
- No public or protected API changes.
discoverFilters()is private. - There's one edge case. Today, if
app/Config/Filters.phpdeclared some class other thanConfig\Filters, discovery wouldincludeit. After this change, that file is skipped. This layout breaks the framework's own conventions, and filter discovery has been deprecated since 4.4.2. So no changelog or upgrade-guide entry is planned.
Tests
Add a regression test in tests/system/Filters/FiltersTest.php. It uses a spy FileLocator, injected with Services::injectMock('locator', ...), that records the paths passed to getClassname(). The test asserts that:
getClassname()is never called for the app or systemConfig/Filters.php.getClassname()is still called fortests/_support/Config/Filters.php, and thetest-customfilteralias it adds is still registered.
The existing discovery test (FiltersTest.php:488) keeps covering the third-party path.
Related
- #10615. It covers config construction cost. This issue is independent and can land separately.
- 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 4/5 3-5 días Aptitud para principiantes 35/100
codeigniter4/CodeIgniter4#10618 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 3/5 1-2 días Aptitud para principiantes 62/100
codeigniter4/CodeIgniter4#10617 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 25/100
codeigniter4/CodeIgniter4#10615 ·
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
-
Python 3.15 supportPosiblemente ocupada @amnesiaof la tomó hoy. AbiertoL: python L: python:uv
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
dependabot/dependabot-core#16524 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
crazy-goat/rabbit-stream#830 ·
Los mantenedores suelen responder en 1 día
-
sync-en
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Los mantenedores suelen responder en 1 día
-
sync-en
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 4 días
-
Перевод устарел
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100