Skip to content

Conversation

@arturmelanchyk
Copy link
Contributor

@arturmelanchyk arturmelanchyk commented Oct 29, 2025

Description

This PR drops unneeded pointers in the Request. This change doesn't affect Request's public API.
As a result GC now needs to scan 2.5% less bytes, also now new Request instantiation is 4% faster

╰─⠠⠵ benchstat old.txt new.txt
goos: darwin
goarch: arm64
pkg: github.com/gofiber/fiber/v3/client
cpu: Apple M3 Max
                   │   old.txt   │              new.txt               │
                   │   sec/op    │   sec/op     vs base               │
RequestHeapScan-16   183.1µ ± 1%   175.8µ ± 1%  -3.98% (p=0.000 n=20)

                   │      old.txt       │                  new.txt                  │
                   │ scan-bytes-heap/op │ scan-bytes-heap/op  vs base               │
RequestHeapScan-16        2222.7Ti ± 1%        2166.9Ti ± 1%  -2.51% (p=0.000 n=20)

                   │       old.txt       │                  new.txt                   │
                   │ scan-bytes-total/op │ scan-bytes-total/op  vs base               │
RequestHeapScan-16         2222.7Ti ± 1%         2166.9Ti ± 1%  -2.51% (p=0.000 n=20)

                   │   old.txt    │            new.txt             │
                   │     B/op     │     B/op      vs base          │
RequestHeapScan-16   10.77Ki ± 0%   10.76Ki ± 0%  ~ (p=0.311 n=20)

                   │   old.txt   │              new.txt               │
                   │  allocs/op  │  allocs/op   vs base               │
RequestHeapScan-16   1.256k ± 0%   1.252k ± 0%  -0.32% (p=0.000 n=20)

Changes introduced

List the new features or adjustments introduced in this pull request. Provide details on benchmarks, documentation updates, changelog entries, and if applicable, the migration guide.

  • Benchmarks: Describe any performance benchmarks and improvements related to the changes.
  • Documentation Update: Detail the updates made to the documentation and links to the changed files.
  • Changelog/What's New: Include a summary of the additions for the upcoming release notes.
  • Migration Guide: If necessary, provide a guide or steps for users to migrate their existing code to accommodate these changes.
  • API Alignment with Express: Explain how the changes align with the Express API.
  • API Longevity: Discuss the steps taken to ensure that the new or updated APIs are consistent and not prone to breaking changes.
  • Examples: Provide examples demonstrating the new features or changes in action.

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)
  • Enhancement (improvement to existing features and functionality)
  • Documentation update (changes to documentation)
  • Performance improvement (non-breaking change which improves efficiency)
  • Code consistency (non-breaking change which improves code reliability and robustness)

Checklist

Before you submit your pull request, please make sure you meet these requirements:

  • Followed the inspiration of the Express.js framework for new functionalities, making them similar in usage.
  • Conducted a self-review of the code and provided comments for complex or critical parts.
  • Updated the documentation in the /docs/ directory for Fiber's documentation.
  • Added or updated unit tests to validate the effectiveness of the changes or new features.
  • Ensured that new and existing unit tests pass locally with the changes.
  • Verified that any new dependencies are essential and have been agreed upon by the maintainers/community.
  • Aimed for optimal performance with minimal allocations in the new code.
  • Provided benchmarks for the new code to analyze and improve upon.

Commit formatting

Please use emojis in commit messages for an easy way to identify the purpose or intention of a commit. Check out the emoji cheatsheet here: CONTRIBUTING.md

…est instantiation and ~2.5% less GC scan bytes)

Signed-off-by: Artur Melanchyk <[email protected]>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 29, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Converts several Request struct fields from pointer types to value types and updates initialization and access accordingly. Adds a new benchmark measuring GC heap/total scan bytes during batched Request Acquire/Release.

Changes

Cohort / File(s) Summary
Request struct refactor
client/request.go
Converts fields from pointer types to value types: header (*Header → Header), params (*QueryParam → QueryParam), cookies (*Cookie → Cookie), path (*PathParam → PathParam), formData (*FormData → FormData). Updates requestPool.New() to initialize value instances and adjusts methods (e.g., Cookie(), PathParam()) to index into value fields.
Test helper update
client/hooks_test.go
Updates newBenchmarkRequest to initialize formData as a value (FormData{...}) instead of a pointer.
New benchmark
client/request_bench_test.go
Adds BenchmarkRequestHeapScan to sample /gc/scan/heap:bytes and /gc/scan/total:bytes, creating/releases batches of Requests via AcquireRequest/ReleaseRequest and reporting per-op scan bytes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Inspect client/request.go for correct semantics after pointer→value conversions (method receivers, zero values, copying costs).
  • Verify requestPool.New() initialization and any pool reuse semantics.
  • Review benchmark for correct metric sampling and that GC/timing suspension doesn't skew results.

Possibly related PRs

Suggested labels

🧹 Updates, v3, ⚡️ Performance

Suggested reviewers

  • sixcolors
  • efectn
  • gaby
  • ReneWerner87

Poem

🐇 I hopped through code with tiny paws,

Swapped pointers for values with gentle laws.
Benchmarks hum as GC takes a peek,
Requests now leaner, swift and sleek —
A rabbit's nod to changes unique.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed The pull request description follows the provided template structure and contains all essential sections: a clear Description explaining the change doesn't affect the public API and provides quantified benefits; a Changes Introduced section with appropriately checked and unchecked items (Benchmarks checked with detailed performance data, other items unchecked as they don't apply to a non-breaking performance improvement); a Type of Change section correctly identifying this as a Performance Improvement; and a Checklist section. The author appropriately recognized that documentation updates, migration guides, and examples are unnecessary since the change is internal and doesn't alter the public API. The benchmark data provided is comprehensive with actual measurements demonstrating the claimed improvements.
Title Check ✅ Passed The title "🚀 perf: Inline Request state wrappers" is directly related to the main change in the PR. The changeset converts pointer-based fields in the Request struct (header, params, cookies, path, formData) to value-based fields, which is the essence of "inlining" these wrapper types. The term accurately reflects the refactoring approach taken in the code changes, and the "perf:" prefix appropriately signals this is a performance optimization. The title is specific and clear enough for a developer scanning commit history to understand that this PR optimizes Request internals by removing pointer indirection.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

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

@codecov
Copy link

codecov bot commented Oct 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.24%. Comparing base (83cc132) to head (646f3a2).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3827      +/-   ##
==========================================
+ Coverage   92.20%   92.24%   +0.04%     
==========================================
  Files         115      115              
  Lines        9671     9671              
==========================================
+ Hits         8917     8921       +4     
+ Misses        482      478       -4     
  Partials      272      272              
Flag Coverage Δ
unittests 92.24% <100.00%> (+0.04%) ⬆️

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.

@arturmelanchyk arturmelanchyk marked this pull request as ready for review October 29, 2025 12:25
@arturmelanchyk arturmelanchyk requested a review from a team as a code owner October 29, 2025 12:25
@gaby gaby requested a review from Copilot October 29, 2025 12:27
@gaby
Copy link
Member

gaby commented Oct 29, 2025

@codex review

Copy link
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: 0

🧹 Nitpick comments (1)
client/request.go (1)

327-327: Optional: Remove unnecessary parentheses.

The parentheses around r.cookies and r.path are redundant since these are now value-type maps. Direct indexing works without them:

-	if val, ok := (r.cookies)[key]; ok {
+	if val, ok := r.cookies[key]; ok {
-	if val, ok := (r.path)[key]; ok {
+	if val, ok := r.path[key]; ok {

Also applies to: 366-366

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 83cc132 and 4d85de4.

📒 Files selected for processing (3)
  • client/hooks_test.go (1 hunks)
  • client/request.go (4 hunks)
  • client/request_bench_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Apply formatting using gofumpt (Make target: format)
Optimize struct field alignment using betteralign (Make target: betteralign)
Modernize code using gopls modernize (Make target: modernize)

Files:

  • client/request.go
  • client/hooks_test.go
  • client/request_bench_test.go
🧬 Code graph analysis (3)
client/request.go (1)
client/client.go (1)
  • Client (37-67)
client/hooks_test.go (1)
client/request.go (1)
  • FormData (874-876)
client/request_bench_test.go (1)
client/request.go (3)
  • Request (46-73)
  • AcquireRequest (983-989)
  • ReleaseRequest (993-996)
🔇 Additional comments (4)
client/request.go (2)

50-57: LGTM! Core refactor correctly reduces pointer indirection.

Converting these fields from pointers to value types reduces GC scan pressure for pooled Request objects while maintaining the public API. The approach aligns well with the PR's performance goals.


970-976: Run betteralign locally to verify struct field alignment.

The initialization code (lines 970-976) correctly uses value types. However, betteralign is not available in the sandbox environment. Per coding guidelines, you must run the following on your local machine to verify optimal struct field alignment:

betteralign -test_files=false ./client

Review the output for the Request struct to ensure fields are optimally ordered to minimize memory padding.

client/hooks_test.go (1)

796-796: LGTM! Test helper correctly updated.

The formData initialization properly uses the value type FormData, consistent with the Request struct refactoring.

client/request_bench_test.go (1)

12-57: LGTM! Benchmark correctly measures heap scan impact.

The benchmark design is sound:

  • Explicit GC calls (acknowledged with revive comments) are necessary to capture scan metrics
  • Timer isolation correctly measures only request creation time
  • Metrics are reported per-iteration (batch of 512 requests), which aligns with the cumulative scan-bytes values mentioned in the PR objectives

Copy link
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 optimizes memory allocation by changing several fields in the Request struct from pointer types to value types, reducing the number of heap allocations per request. Additionally, a new benchmark test is introduced to measure GC heap scan overhead.

  • Changed Request struct fields from pointer to value types: header, params, cookies, path, and formData
  • Added BenchmarkRequestHeapScan to measure GC scanning overhead during request allocation and release
  • Updated pool initialization and test helpers to reflect the new non-pointer field types

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
client/request.go Changed five Request struct fields from pointer to value types and updated initialization in the request pool
client/request_bench_test.go Added new benchmark to measure heap scan metrics for request batches
client/hooks_test.go Updated test helper to use value type instead of pointer for formData field

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Hooray!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Member

@gaby gaby left a comment

Choose a reason for hiding this comment

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

LGTM

@gaby gaby changed the title 🚀 perf: inline Request state wrappers to cut GC scan (~4% faster request instantiation and ~2.5% less GC scan bytes) 🚀 perf: Inline Request state wrappers Oct 29, 2025
@gaby gaby added this to v3 Oct 29, 2025
@gaby gaby added this to the v3 milestone Oct 29, 2025
@ReneWerner87
Copy link
Member

ReneWerner87 commented Oct 29, 2025

  • @gaby will check the bench with his x86 AMD, since most the majority of users use this in prod

@arturmelanchyk
Copy link
Contributor Author

got similar results on VPS with 2x dedicated AMD EPYC vCPU, overall boost is still ~3%, but without gains on GC side

root@ubuntu-8gb-hel1-1:~/fiber/client# go run golang.org/x/perf/cmd/benchstat@latest old.txt new.txt 
goos: linux
goarch: amd64
pkg: github.com/gofiber/fiber/v3/client
cpu: AMD EPYC-Milan Processor
                  │   old.txt   │              new.txt               │
                  │   sec/op    │   sec/op     vs base               │
RequestHeapScan-2   126.1µ ± 0%   122.3µ ± 0%  -3.02% (p=0.000 n=20)

                  │      old.txt       │                  new.txt                  │
                  │ scan-bytes-heap/op │ scan-bytes-heap/op  vs base               │
RequestHeapScan-2        1677.7Ti ± 0%        1677.7Ti ± 0%  -0.00% (p=0.001 n=20)

                  │       old.txt       │                  new.txt                   │
                  │ scan-bytes-total/op │ scan-bytes-total/op  vs base               │
RequestHeapScan-2         1677.7Ti ± 0%         1677.7Ti ± 0%  -0.00% (p=0.001 n=20)

                  │   old.txt    │               new.txt               │
                  │     B/op     │     B/op      vs base               │
RequestHeapScan-2   5.757Ki ± 0%   5.737Ki ± 0%  -0.35% (p=0.001 n=20)

                  │   old.txt   │              new.txt               │
                  │  allocs/op  │  allocs/op   vs base               │
RequestHeapScan-2   1.252k ± 0%   1.249k ± 0%  -0.24% (p=0.000 n=20)

@ReneWerner87 ReneWerner87 merged commit ba9d619 into gofiber:main Oct 30, 2025
15 checks passed
@github-project-automation github-project-automation bot moved this to Done in v3 Oct 30, 2025
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.

3 participants