refactor: simplify and optimize handleRequest method in CodeIgniter#10369
refactor: simplify and optimize handleRequest method in CodeIgniter#10369gr8man wants to merge 1 commit into
Conversation
36c2a86 to
76b6aac
Compare
michalsn
left a comment
There was a problem hiding this comment.
I agree there is one real issue here: when startController() returns a ResponseInterface, the old flow can call gatherOutput() twice. Fixing that redundant call is reasonable.
However, I don't think this refactor should be merged as-is.
- Lazy URI Resolution: The
$this->request->getPath()call has been moved insideapplyFilters(), meaning URI resolution is only performed when filters are enabled ($this->enableFilters === true), avoiding unnecessary string calculations.
I think this is false as an optimization. Routing still calls getPath() unconditionally, and IncomingRequest::getPath() is only a property read. This does not justify the refactor.
- Early Response Return: Added an early
return;insideserveResponse()ifstartController()returns aResponseInterfaceinstance (e.g. from filter attributes or closure routes). This avoids redundant calls tohandleCache()/gatherOutput()which ended output buffering and processed the response body twice in the original implementation.
This should be extracted as the only kept change.
- No Redundant Wrappers: We call the existing
tryToRouteIt()method directly insidehandleRequest()instead of creating a redundantresolveRoute()wrapper.
The supposed avoided wrapper did not exist in the original code, while this PR adds a new redundant wrapper: handleCache().
Performance Comparison (2,000 Iterations) A realistic benchmark simulating a full request lifecycle (routing to
Home::indexcontroller, rendering thewelcome_messageview, and executinginvalidcharsbefore filter plussecureheadersandtoolbarafter filters) was run to compare the two branches.
...
The refactoring reduces the average request execution time by ~6.8% while maintaining identical peak memory usage.
I ran the benchmark script locally and couldn't reproduce the ~6.8% improvement. Across 10 runs per branch, the refactored branch was actually a bit slower, both by average and by median.
That matches my earlier doubts about this benchmark. There are also problems with the script itself: as far as I can tell it doesn't actually enable the filters it claims to, and it never triggers the ResponseInterface short-circuit, which is the one code path this PR really changes. The per-iteration reset also doesn't match what the FrankenPHP worker loop does between requests, so it's not measuring the scenario it claims to.
| * @param string $position 'before' or 'after' | ||
| * @param list<string>|string|null $routeFilters | ||
| */ | ||
| protected function applyFilters(string $position, $routeFilters = null): ?ResponseInterface |
There was a problem hiding this comment.
I don't think this helper should be added. It turns the existing inline before/after flow into a new protected abstraction, but the two branches still have different contracts.
| // we need to ensure it's active for the current request | ||
| if ($position === 'before') { | ||
| if ($routeFilters !== null) { | ||
| if (is_string($routeFilters)) { |
There was a problem hiding this comment.
This should be removed with the refactor. Router::getFilters() returns array / list<string>.
| $this->handleCache($cacheConfig, $returned); | ||
|
|
||
| return; | ||
| } |
There was a problem hiding this comment.
This is the only behavior change here that I think is worth keeping: avoid the previous duplicate gatherOutput() call when startController() returns a ResponseInterface. Please extract this as a minimal targeted change in the original flow rather than keeping the surrounding refactor.
| * | ||
| * @param mixed $returned | ||
| */ | ||
| protected function handleCache(Cache $cacheConfig, $returned): void |
There was a problem hiding this comment.
Please remove. It does not handle caching. It only forwards to gatherOutput(), whose $cacheConfig parameter is already deprecated.
fddc099 to
6f9842e
Compare
6f9842e to
efcbfae
Compare
Description
This PR refactors the
handleRequest()method insystem/CodeIgniter.php.Originally,
handleRequest()was a 109-line method with high complexity, managing routing, filters, controller dispatching, output buffering, and caching within a single block.This change simplifies the method by delegating these concerns to three smaller, focused helper methods:
applyFilters(string $position, $routeFilters = null): ?ResponseInterface— Runs global and route-specific filters.serveResponse(Cache $cacheConfig, $returned): void— Creates/runs the controller and gathers the output.handleCache(Cache $cacheConfig, $returned): void— A wrapper around output gathering and caching.Optimizations Implemented
$this->request->getPath()call has been moved insideapplyFilters(), meaning URI resolution is only performed when filters are enabled ($this->enableFilters === true), avoiding unnecessary string calculations.return;insideserveResponse()ifstartController()returns aResponseInterfaceinstance (e.g. from filter attributes or closure routes). This avoids redundant calls tohandleCache()/gatherOutput()which ended output buffering and processed the response body twice in the original implementation.tryToRouteIt()method directly insidehandleRequest()instead of creating a redundantresolveRoute()wrapper.Performance Comparison (2,000 Iterations)
A realistic benchmark simulating a full request lifecycle (routing to
Home::indexcontroller, rendering thewelcome_messageview, and executinginvalidcharsbefore filter plussecureheadersandtoolbarafter filters) was run to compare the two branches.Original
developbranch:Refactored branch (
refactor/codeigniter-handle-request):The refactoring reduces the average request execution time by ~6.8% while maintaining identical peak memory usage.
Benchmark Script Code
Checklist: