perf: filter discovery tokenizes the app and system `Config/Filters.php` on every request
Mantenedores costumam responder em até 1 dia
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 2/5
- Tempo estimado
- 1-3 horas
- Facilidade para iniciantes
- 72/100
- Tipo de issue
- Refatoração
- Clareza
- Claramente especificada
- Status de atividade
- Ativa
- Stack de tecnologia
- php
- Domínio
- backend, performance
Direção de pesquisa
Comece no método privado discoverFilters(), chamado a partir do construtor de Filters, e veja como os resultados de FileLocator::search() são passados para getClassname(). Adicione uma verificação que ignore os caminhos APPPATH e SYSTEMPATH Config/Filters.php antes dessa chamada, deixando os outros caminhos inalterados. Execute tests/system/Filters/FiltersTest.php; está pronto quando um locator espião, injetado via Services::injectMock('locator', ...), não mostrar nenhuma chamada a getClassname() para os arquivos da aplicação ou do sistema, e o filtro customizado em tests/_support e seu alias test-customfilter continuarem funcionando.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
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.
- Linguagem predominante
- PHP
- Estrelas
- 6k
- Forks
- 2k
- Merge médio
- 1d 22h
- PRs com merge (30d)
- 59
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Tem um modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de codeigniter4/CodeIgniter4
-
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 35/100
codeigniter4/CodeIgniter4#10618 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 62/100
codeigniter4/CodeIgniter4#10617 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 25/100
codeigniter4/CodeIgniter4#10615 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
bug
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 48/100
codeigniter4/CodeIgniter4#10589 · 3 comentários ·
Mantenedores costumam responder em até 1 dia
-
dev
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 25/100
codeigniter4/CodeIgniter4#10427 · 5 comentários ·
Mantenedores costumam responder em até 1 dia
Todas as issues de codeigniter4/CodeIgniter4
Issues semelhantes
-
sync-en
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
Mantenedores costumam responder em até 1 dia
-
sync-en
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 72/100
Mantenedores costumam responder em até 4 dias
-
Перевод устарел
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 85/100
-
bug
Dificuldade 2/5 Meio dia Facilidade para iniciantes 76/100
m3ue/m3u-editor#1604 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 70/100
femiwiki/docker-mediawiki#1497 ·
Mantenedores costumam responder em até 1 dia