Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

perf: filter discovery tokenizes the app and system `Config/Filters.php` on every request

オープン 初心者向け
#10,616 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
72/100
issue の種類
リファクタリング
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
php

調査の方向性

プライベートメソッド discoverFilters() から始めてください。このメソッドは Filters のコンストラクタから呼び出されます。そして FileLocator::search() の結果が getClassname() にどのように渡されているかを確認してください。その呼び出しの前に、APPPATH と SYSTEMPATH の Config/Filters.php パスをスキップするチェックを追加してください。他のパスは変更しないでください。tests/system/Filters/FiltersTest.php を実行します。完了の条件は、Services::injectMock('locator', ...) で差し込んだスパイ locator が、アプリおよびシステムのファイルに対して getClassname() の呼び出しを示さないこと、そして tests/_support のカスタムフィルターとそのエイリアス test-customfilter が引き続き動作することです。

索引モデルが issue の本文から書いたものです。

説明

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.php
  • system/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, and APPPATH and SYSTEMPATH are 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.php declared some class other than Config\Filters, discovery would include it. 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 system Config/Filters.php.
  • getClassname() is still called for tests/_support/Config/Filters.php, and the test-customfilter alias 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.
主要言語
PHP
スター
6k
フォーク
2k
平均マージ
1日 22時間
マージ済み PR(30日)
59

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

codeigniter4/CodeIgniter4 のほかの issue

codeigniter4/CodeIgniter4 の issue をすべて見る

似ている issue

PHP の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。