Skip to content

perf: improve Headers class performance - #5699

Open
anonrig wants to merge 2 commits into
nodejs:mainfrom
anonrig:cursor/headers-class-performance-859a
Open

perf: improve Headers class performance#5699
anonrig wants to merge 2 commits into
nodejs:mainfrom
anonrig:cursor/headers-class-performance-859a

Conversation

@anonrig

@anonrig anonrig commented Aug 18, 2026

Copy link
Copy Markdown
Member

This relates to...

N/A

Rationale

Headers is on the fetch / Request / Response hot path. The current implementation pays for WebIDL conversion, token validation, and toLowerCase() as separate passes, and stores every entry as a { name, value } object.

Changes

  • Combine ByteString conversion, HTTP token validation, and lowercasing into a single pass.
  • Fast-path common lowercase names (content-type, accept, authorization, …) on get / has / delete.
  • Store values as strings in the internal Map instead of { name, value } objects. Original casing is kept in a side table only when it differs from the lowercase name.
  • Copy an existing Headers instance by cloning the list instead of re-validating every entry.
  • Keep the existing fetch spec comments next to the new hot-path code. No changes outside lib/web/fetch/headers.js.

No intended behavioral change. Guard handling, set-cookie / getSetCookie(), iteration order, and original-name casing on the wire are preserved.

Features

N/A

Bug Fixes

N/A

Breaking Changes and Deprecations

N/A

Benchmark

Measured with the source Headers class (Node v22.14.0, 200k iterations, paired old vs new):

Operation Before After Change
get (custom name) 18.4M ops/s 77.9M ops/s 4.2x
get (content-type) 17.6M ops/s 56.2M ops/s 3.2x
has 16.7M ops/s 80.7M ops/s 4.8x
set 15.4M ops/s 25.2M ops/s +64%
new Headers(headers) 1.12M ops/s 1.72M ops/s +54%
new Headers() 23.7M ops/s 23.3M ops/s ~same
append 4.36M ops/s 4.33M ops/s ~same
iterate 5.05M ops/s 5.15M ops/s ~same

Status

Tested locally:

node --test test/fetch/headers.js test/fetch/headers-inspect-custom.js test/fetch/headerslist-sortedarray.js test/fetch/headers-case.js

All 70 tests passed, including the 4000-iteration toSortedArray fast/slow paths and the fetch cloning cases.

Speed up the WHATWG Headers hot path:

- Combine ByteString conversion, token validation, and lowercasing
  into a single pass, with a fast path for common lowercase names.
- Store header values as strings instead of {name, value} objects.
- Copy an existing Headers list without re-validating every entry.
- Skip ToString in the ByteString converter when the value is already
  a string.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Keep the Headers hot-path changes, but put the fetch spec comments
back and drop the unrelated ByteString converter change.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>
cursor Bot pushed a commit to anonrig/node that referenced this pull request Aug 18, 2026
Add WHATWG Headers unit tests and a fetch/headers benchmark so Node
can track the API after the implementation change lands in undici.

Refs: nodejs/undici#5699
Co-authored-by: Yagiz Nizipli <yagiz@nizipli.com>
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
@codecov-commenter

codecov-commenter commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.64151% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.46%. Comparing base (f387057) to head (30f9119).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
lib/web/fetch/headers.js 97.64% 10 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5699      +/-   ##
==========================================
- Coverage   93.47%   93.46%   -0.01%     
==========================================
  Files         110      110              
  Lines       38846    39119     +273     
==========================================
+ Hits        36310    36562     +252     
- Misses       2536     2557      +21     

☔ View full report in Codecov by Harness.
📢 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Adding the benchmarks somewhere will be good.

Also, lint is failing.

@KhafraDev I'm generically ok with these improvements. However it's quite substantial in the code changes. Take a look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants