perf: filter discovery tokenizes the app and system `Config/Filters.php` on every request
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Anfängerfreundlichkeit
- 72/100
- Issue-Typ
- Refactoring
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- php
- Bereich
- backend, performance
Rechercherichtung
Beginne in der privaten Methode discoverFilters(), die vom Konstruktor von Filters aufgerufen wird, und prüfe, wie die Ergebnisse von FileLocator::search() an getClassname() übergeben werden. Füge vor diesem Aufruf eine Prüfung hinzu, die die Pfade APPPATH und SYSTEMPATH Config/Filters.php überspringt; andere Pfade bleiben unverändert. Führe tests/system/Filters/FiltersTest.php aus. Fertig ist es, wenn ein Spy-Locator über Services::injectMock('locator', ...) keinen Aufruf von getClassname() für die App- oder Systemdateien zeigt, während der Custom-Filter in tests/_support und sein Alias test-customfilter weiterhin funktionieren.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
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.
- Vorherrschende Sprache
- PHP
- Sterne
- 6k
- Forks
- 2k
- Ø Merge
- 1 T. 22 Std.
- Gemergte PRs (30 T.)
- 59
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Hat eine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus codeigniter4/CodeIgniter4
-
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 35/100
codeigniter4/CodeIgniter4#10618 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 62/100
codeigniter4/CodeIgniter4#10617 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 25/100
codeigniter4/CodeIgniter4#10615 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 48/100
codeigniter4/CodeIgniter4#10589 · 3 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
dev
Schwierigkeit 5/5 Über eine Woche Anfängerfreundlichkeit 25/100
codeigniter4/CodeIgniter4#10427 · 5 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in codeigniter4/CodeIgniter4
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
matomo-org/device-detector#8405 ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 66/100
Maintainer antworten meist innerhalb von 1 Tag
-
sync-en
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 62/100
Maintainer antworten meist innerhalb von 1 Tag
-
sync-en
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 66/100
Maintainer antworten meist innerhalb von 4 Tagen