Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

perf: skip redundant work in `RouteCollection::create()` during route registration

未關閉
#10,617 1 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

維護者通常 1 天內回覆

還沒有人認領這個 Issue。

評估

難度
3/5
預估耗時
1-2 天
新手友好度
62/100
Issue 類型
重構
描述清晰度
基本清楚
活躍度
活躍
技術堆疊
php

研究方向

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.

由索引模型根據 Issue 內容生成。

描述

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() runs str_ireplace(':' . $tag, ...) once for every registered placeholder (6 by default), even when $from has no : and nothing can match. That costs about 0.50 µs per route.
  • helper('array'). It's called on every create(). RouteCollection no 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

  1. In create(), run the placeholder loop only when the route key contains :. If it has no :, no str_ireplace can match, and no replacement can add a :. So the output is identical. That includes custom placeholders whose patterns contain :, such as (?:...).
  2. Call helper('array') only on the first create() 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 in create(). Apps can replace esc() in app/Common.php, so skipping the call would quietly bypass a custom version on route paths. A faster esc() for the html context 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
主要語言
PHP
星號
6k
分支
2k
平均合併
1 天 22 小時
30 天內合併 PR
59

環境準備

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

codeigniter4/CodeIgniter4 的其他 Issue

查看 codeigniter4/CodeIgniter4 的全部 Issue

相似的 Issue

更多 PHP Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。