Skip to content

refactor: streamline request handler selection and context management for improved performance#4233

Merged
ReneWerner87 merged 6 commits into
mainfrom
performance-3
May 5, 2026
Merged

refactor: streamline request handler selection and context management for improved performance#4233
ReneWerner87 merged 6 commits into
mainfrom
performance-3

Conversation

@ReneWerner87
Copy link
Copy Markdown
Member

@ReneWerner87 ReneWerner87 commented Apr 25, 2026

Optimizes Fiber’s default request hot path while preserving custom context behavior and panic-safe context cleanup.

Changes:

  • split default and custom request handling so the common *DefaultCtx path avoids unnecessary interface/type dispatch
  • keep default context cleanup panic-safe with a single deferred release
  • make default-context acquisition resilient if a custom context reaches the pool
  • centralize flash-cookie detection through hasFlashCookie
  • reduce request path processing work by combining detection-path copy and lowercase handling
  • reuse path string views during router matching
  • avoid unnecessary release/reset work for default request/response helpers and nil viewBindMap

Benchmarks:

  • Benchmark_Communication_Flow: 39.88 ns/op -> 35.71 ns/op
  • Benchmark_Router_Next_Default: 33.23 ns/op -> 30.23 ns/op
  • Benchmark_Router_Handler: 77.84 ns/op -> 75.97 ns/op
  • Benchmark_Router_Chain: unchanged in final review-safe version

No allocation regressions.

Copilot AI review requested due to automatic review settings April 25, 2026 13:38
@ReneWerner87 ReneWerner87 requested a review from a team as a code owner April 25, 2026 13:38
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 25, 2026

Walkthrough

A centralized request-handler selection (new selectRequestHandler) picks between defaultRequestHandler and customRequestHandler based on app.hasCustomCtx. Context acquisition/release is refactored with pooled DefaultCtx helpers and a userContextSet flag. Path lowercasing moved to appendLowerBytes and route matching reuses cached path strings.

Changes

Request Handler Selection & Context Management Refactor

Layer / File(s) Summary
Data Shape & Tracking
ctx.go, errors_internal.go, req_interface_gen.go, res_interface_gen.go
DefaultCtx gains userContextSet bool. New sentinel errDefaultCtxTypeAssertion. release() removed from exported Req and Res interfaces.
Context Acquisition & Release Helpers
ctx_interface.go
Adds acquireDefaultCtx, prepareDefaultCtx, setHandlerCtxIfNeeded, isCustomCtx, and releaseDefaultCtx to centralize pooled DefaultCtx obtain/return and to handle CustomCtx fallback paths. AcquireCtx updated to use these helpers.
Handler Selection Logic
app.go
Introduces selectRequestHandler() and updates App.init(), App.Handler(), and App.setCtxFunc() to assign the server handler from the selector instead of a hard-coded requestHandler.
Request Dispatch Refactoring
router.go
Splits former requestHandler into defaultRequestHandler and customRequestHandler. Both validate method, clear flash cookie when present, call app.next/app.nextCustom, and route errors through ctx.App().ErrorHandler.
Path Lowercasing & Matching
path.go, ctx.go, router.go
Adds appendLowerBytes(dst, src []byte) for ASCII-lowercasing. configDependentPaths() now uses it; route matching caches detectionPath and path once per request (replacing repeated UnsafeString calls).
Context Release & Safety
ctx.go, req.go, res.go
DefaultCtx.release() now clears fasthttp user value only if userContextSet is true, nil-guards viewBindMap, and removed calls to DefaultReq.release()/DefaultRes.release(). Internal DefaultReq.release() and DefaultRes.release() were deleted.
Tests / Validation
ctx_test.go
Adds tests: Test_App_AcquireDefaultCtx_CustomCtxFallback, Test_App_SetHandlerCtxIfNeeded_CustomCtxFallback, and Test_Ctx_Release_UserContextSetWithoutFastHTTP.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant fasthttp
    participant App
    participant Router
    participant DefaultCtxPool

    Client->>fasthttp: HTTP request
    fasthttp->>App: invoke Handler (selectRequestHandler)
    App->>App: selectRequestHandler() -> default/custom handler
    App->>DefaultCtxPool: acquireDefaultCtx (if default)
    DefaultCtxPool-->>App: *DefaultCtx
    App->>Router: next / nextCustom with context
    Router->>Router: route.match(detectionPath, path)
    Router-->>App: handler result / error
    App->>DefaultCtxPool: releaseDefaultCtx (if default)
    App->>fasthttp: write response
    fasthttp->>Client: HTTP response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • efectn
  • sixcolors

Poem

🐰
I hopped through bytes and paths today,
Chose handlers swift where requests now play,
Pooled contexts tucked safe in rows,
Lowercased paths where cool winds blow,
Release, return — the garden grows.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main focus of the pull request—refactoring request handler selection and context management for performance improvements—which directly aligns with the comprehensive changes made across multiple files.
Description check ✅ Passed The PR description provides a clear summary of changes, includes specific benchmarks demonstrating performance improvements, and lists the key optimizations made. However, it does not follow the repository's template structure or explicitly address required checklist items like testing, documentation updates, or API alignment.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch performance-3

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 25, 2026

Codecov Report

❌ Patch coverage is 82.35294% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.11%. Comparing base (6bf3888) to head (ab42d50).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
ctx_interface.go 72.41% 5 Missing and 3 partials ⚠️
router.go 82.14% 3 Missing and 2 partials ⚠️
ctx.go 80.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4233      +/-   ##
==========================================
- Coverage   91.25%   91.11%   -0.15%     
==========================================
  Files         127      127              
  Lines       12556    12605      +49     
==========================================
+ Hits        11458    11485      +27     
- Misses        687      702      +15     
- Partials      411      418       +7     
Flag Coverage Δ
unittests 91.11% <82.35%> (-0.15%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ReneWerner87 ReneWerner87 marked this pull request as draft April 25, 2026 13:39
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request optimizes the request handling path by introducing specialized handlers (defaultRequestHandler and customRequestHandler) to avoid interface assertions and unnecessary defer calls. It refactors context management, including a more efficient way to acquire and release default contexts, and optimizes path handling and flash cookie detection. Additionally, it updates documentation and removes redundant release methods from the request and response interfaces. I have no feedback to provide.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors Fiber’s request handling path to reduce per-request overhead, primarily by splitting default vs custom context request handlers and tightening hot-path operations in routing and context management.

Changes:

  • Introduces separate defaultRequestHandler and customRequestHandler, and selects between them via selectRequestHandler().
  • Reduces allocations/overhead in routing and path handling (precomputes unsafe string conversions; replaces lowercasing helper with a local fast-path).
  • Adjusts context lifecycle cleanup (tracks whether a user context was stored; simplifies req/res release mechanics; updates related interface docs).

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
router.go Precomputes route match strings; splits request handlers; inlines some hot-path checks.
app.go Routes fasthttp handler setup through selectRequestHandler() for default/custom ctx.
ctx_interface.go Adds acquireDefaultCtx to avoid interface/type assertion overhead in default path.
ctx.go Optimizes detection-path lowercasing; refines user-context storage/cleanup; removes req/res release calls.
errors_internal.go Adds a dedicated panic error for default ctx pool type assertion failures.
req_interface_gen.go Doc clarifications around multipart parsing respecting BodyLimit; removes release() from interface.
req.go Removes DefaultReq.release() implementation.
res_interface_gen.go Doc tweaks; clarifies getLocationFromRoute semantics; removes release() from interface.
res.go Removes DefaultRes.release() implementation.
ctx_interface_gen.go Mirrors doc clarifications for multipart + AutoFormat and getLocationFromRoute.

Comment thread router.go
Comment thread router.go Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
ctx.go (1)

669-678: Consider expressing appendLowerBytes via utils/v2.

utils.ToLowerBytes already provides a lookup-table-based ASCII lower-case in github.com/gofiber/utils/v2. The current single call site can be written as:

♻️ Optional refactor
-	if !c.app.config.CaseSensitive {
-		c.detectionPath = appendLowerBytes(c.detectionPath, c.path)
-	} else {
-		c.detectionPath = append(c.detectionPath[:0], c.path...)
-	}
+	c.detectionPath = append(c.detectionPath[:0], c.path...)
+	if !c.app.config.CaseSensitive {
+		c.detectionPath = utils.ToLowerBytes(c.detectionPath)
+	}

…and appendLowerBytes can be removed.

This trades the current single-pass copy+lower for a copy followed by an in-place lookup-table lower. Benchmarks should validate which is faster on the targeted hot path; if the single-pass branch wins, ignore. Otherwise, leaning on the shared helper avoids hand-rolling a primitive.

As per coding guidelines: "Prefer github.com/gofiber/utils/v2 helpers (for example, utils.Trim) when performing common operations such as string manipulation, whenever it is practical and appropriate for the surrounding code".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ctx.go` around lines 669 - 678, The function appendLowerBytes implements
ASCII lowercasing manually; replace its single call site to use
utils.ToLowerBytes from github.com/gofiber/utils/v2 and remove appendLowerBytes;
update imports to add utils (or reuse existing utils import), ensure the call
site expects the same behavior (in-place/lowered copy) and run benchmarks if you
want to validate performance before deleting appendLowerBytes.
router.go (1)

442-446: Consolidate flash-cookie checks by using hasFlashCookie helper from both handlers.

defaultRequestHandler duplicates the flash-cookie optimization inline (raw-header scan followed by Cookie(FlashCookieName) != nil), while customRequestHandler calls the existing hasFlashCookie helper that performs the identical checks. Since hasFlashCookie already encodes the optimized fast path (lines 50–61 in redirect.go), replace the inline check in defaultRequestHandler with a call to hasFlashCookie for consistency. This prevents future flash-cookie semantics changes from requiring updates at both call sites.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@router.go` around lines 442 - 446, The inline raw-header +
Cookie(FlashCookieName) check in defaultRequestHandler duplicates logic already
implemented in hasFlashCookie; replace that conditional with a call to
hasFlashCookie so defaultRequestHandler uses the same optimized fast-path
helper, and then call ctx.Redirect().parseAndClearFlashMessages() as before
(i.e., remove the rawHeaders/bytes.Contains branch and invoke hasFlashCookie to
decide whether to parse and clear flash messages).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ctx_interface.go`:
- Around line 84-93: acquireDefaultCtx currently panics if app.pool.Get() isn't
a *DefaultCtx, which can occur during a race if setCtxFunc is called after the
server starts (app.newCtxFunc non-nil → pool.New returns CustomCtx) while
app.server.Handler still points to defaultRequestHandler; to fix, either assert
in setCtxFunc that it must be called before Listen() (e.g., check app.server ==
nil and return or panic with a clear message) or make acquireDefaultCtx
resilient by detecting a non-*DefaultCtx from app.pool.Get() and delegating to
the generic AcquireCtx / customRequestHandler path (release the non-matching
object if needed and obtain a proper ctx via AcquireCtx) so in-flight requests
never panic—update setCtxFunc, acquireDefaultCtx, and any pool.New logic to
implement one of these two approaches.

In `@router.go`:
- Around line 428-463: Add a single deferred cleanup at the start of
defaultRequestHandler to match customRequestHandler (e.g., defer
app.ReleaseCtx(ctx)) so the ctx is always returned to the pool even if
app.next(ctx) or SendStatus panics, then remove the three duplicated blocks that
manually check ctx.abandoned.Load() and call ctx.release(); app.pool.Put(ctx)
(and the early returns that only exist to release the ctx), leaving logic for
methodInt == -1 and error handling intact but relying on ReleaseCtx to do the
actual release and abandonment check.

---

Nitpick comments:
In `@ctx.go`:
- Around line 669-678: The function appendLowerBytes implements ASCII
lowercasing manually; replace its single call site to use utils.ToLowerBytes
from github.com/gofiber/utils/v2 and remove appendLowerBytes; update imports to
add utils (or reuse existing utils import), ensure the call site expects the
same behavior (in-place/lowered copy) and run benchmarks if you want to validate
performance before deleting appendLowerBytes.

In `@router.go`:
- Around line 442-446: The inline raw-header + Cookie(FlashCookieName) check in
defaultRequestHandler duplicates logic already implemented in hasFlashCookie;
replace that conditional with a call to hasFlashCookie so defaultRequestHandler
uses the same optimized fast-path helper, and then call
ctx.Redirect().parseAndClearFlashMessages() as before (i.e., remove the
rawHeaders/bytes.Contains branch and invoke hasFlashCookie to decide whether to
parse and clear flash messages).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cf125ae5-1365-42d9-b24a-bb88f6e37a51

📥 Commits

Reviewing files that changed from the base of the PR and between bec9ba6 and 42bde06.

📒 Files selected for processing (10)
  • app.go
  • ctx.go
  • ctx_interface.go
  • ctx_interface_gen.go
  • errors_internal.go
  • req.go
  • req_interface_gen.go
  • res.go
  • res_interface_gen.go
  • router.go
💤 Files with no reviewable changes (2)
  • req.go
  • res.go

Comment thread ctx_interface.go Outdated
Comment thread router.go
Comment thread ctx_interface.go
@ReneWerner87 ReneWerner87 self-assigned this May 3, 2026
@ReneWerner87
Copy link
Copy Markdown
Member Author

@efectn @ksw2000 can you check this

@ReneWerner87
Copy link
Copy Markdown
Member Author

/gemini review

@ReneWerner87
Copy link
Copy Markdown
Member Author

@coderabbitai review

@ReneWerner87 ReneWerner87 requested a review from Copilot May 4, 2026 11:19
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 4, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors Fiber's request handling logic by introducing specialized handlers for default and custom contexts, which improves performance and type safety. Key updates include the addition of a userContextSet flag to DefaultCtx for optimized cleanup and a new appendLowerBytes utility for path normalization. Review feedback suggests optimizing appendLowerBytes by pre-allocating slice capacity to avoid reallocations in hot paths and adding a defensive nil check for c.fasthttp in the release method to prevent potential panics.

Comment thread path.go
Comment thread ctx.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ctx.go`:
- Around line 649-652: When CaseSensitive is false the code uses
appendLowerBytes to lowercase only ASCII into c.detectionPath, but registered
routes in router.go are normalized using Unicode-aware lowercasing, causing
non-ASCII mismatches (e.g., /Ä vs /ä). Fix by restoring Unicode-safe lowercasing
when c.app.config.CaseSensitive is false: replace the ASCII-only
appendLowerBytes path with the same Unicode-aware normalization used for route
registration (or run a non-ASCII-aware fallback before matching), ensuring
c.detectionPath is produced with the same Unicode lowercasing logic as router.go
so comparisons succeed for non-ASCII characters.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1b12665a-12d9-4c61-a1bd-423c5a23d3aa

📥 Commits

Reviewing files that changed from the base of the PR and between 42bde06 and 5f3f98f.

📒 Files selected for processing (6)
  • app.go
  • ctx.go
  • ctx_interface.go
  • ctx_test.go
  • path.go
  • router.go
✅ Files skipped from review due to trivial changes (1)
  • path.go

Comment thread ctx.go
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Comment thread path.go Outdated
Comment thread router.go
@ReneWerner87 ReneWerner87 marked this pull request as ready for review May 4, 2026 11:29
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
ctx.go (1)

649-652: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Restore Unicode-consistent lowercasing for detection path

Line 650 lowercases request paths with ASCII-only appendLowerBytes, but route normalization still uses Unicode-aware lowercasing (utilsstrings.ToLower) in the same PR branch. With CaseSensitive=false, non-ASCII paths can stop matching (e.g., vs ).

💡 Suggested fix
 import (
 	"context"
 	"crypto/tls"
 	"fmt"
 	"io"
 	"maps"
 	"mime/multipart"
 	"strings"
 	"sync/atomic"
 	"time"

 	"github.com/gofiber/utils/v2"
+	utilsbytes "github.com/gofiber/utils/v2/bytes"
 	"github.com/valyala/bytebufferpool"
 	"github.com/valyala/fasthttp"
 )
@@
 	if !c.app.config.CaseSensitive {
-		c.detectionPath = appendLowerBytes(c.detectionPath, c.path)
+		c.detectionPath = append(c.detectionPath[:0], c.path...)
+		c.detectionPath = utilsbytes.UnsafeToLower(c.detectionPath)
 	} else {
 		c.detectionPath = append(c.detectionPath[:0], c.path...)
 	}

Reference checked:

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ctx.go` around lines 649 - 652, The detection path lowercasing uses
ASCII-only appendLowerBytes when CaseSensitive is false, which breaks
Unicode-aware normalization; change the branch that sets c.detectionPath so it
uses the project's Unicode-aware lowercasing (e.g., utilsstrings.ToLower) on
c.path before appending instead of appendLowerBytes. Update the code around
appendLowerBytes / append(c.detectionPath[:0], c.path...) so that when
c.app.config.CaseSensitive is false you lowercased c.path with
utilsstrings.ToLower (then append the resulting bytes into c.detectionPath)
while keeping the existing non-lowercasing branch unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@ctx.go`:
- Around line 649-652: The detection path lowercasing uses ASCII-only
appendLowerBytes when CaseSensitive is false, which breaks Unicode-aware
normalization; change the branch that sets c.detectionPath so it uses the
project's Unicode-aware lowercasing (e.g., utilsstrings.ToLower) on c.path
before appending instead of appendLowerBytes. Update the code around
appendLowerBytes / append(c.detectionPath[:0], c.path...) so that when
c.app.config.CaseSensitive is false you lowercased c.path with
utilsstrings.ToLower (then append the resulting bytes into c.detectionPath)
while keeping the existing non-lowercasing branch unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d296d3ad-89f7-4bf4-8f72-ef2f4f2d852b

📥 Commits

Reviewing files that changed from the base of the PR and between 5f3f98f and ab42d50.

📒 Files selected for processing (4)
  • ctx.go
  • ctx_interface.go
  • ctx_test.go
  • path.go
✅ Files skipped from review due to trivial changes (1)
  • ctx_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • path.go

@ksw2000
Copy link
Copy Markdown
Member

ksw2000 commented May 4, 2026

@efectn @ksw2000 can you check this

LGTM

@ReneWerner87 ReneWerner87 merged commit 7dc4c9d into main May 5, 2026
20 of 21 checks passed
@ReneWerner87 ReneWerner87 deleted the performance-3 branch May 5, 2026 07:55
@github-project-automation github-project-automation Bot moved this to Done in v3 May 5, 2026
@ReneWerner87 ReneWerner87 removed their assignment May 5, 2026
@ReneWerner87 ReneWerner87 modified the milestones: v3, v3.3.0 May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants