René's URL Explorer Experiment


Title: http: avoid dictionary-mode objects in responses by mcollina · Pull Request #66420 · nodejs/node · GitHub

Open Graph Title: http: avoid dictionary-mode objects in responses by mcollina · Pull Request #66420 · nodejs/node

X Title: http: avoid dictionary-mode objects in responses by mcollina · Pull Request #66420 · nodejs/node

Description: setHeader() stored headers in a { __proto__: null } literal and OutgoingMessage let EventEmitter create the same literal for its listener table. V8 creates null-prototype literals in dictionary mode, so every response paid for a hash table allocation on the first setHeader()/on() call, for runtime-miss stores (the profile shows StoreIC::Store, Factory::NewStoreHandler and TieringManager::NotifyICChanged in steady state) and for dictionary lookups on every header access, including the for...in in _storeHeader(). This PR uses a fast-mode object with an empty null-prototype chain for the headers (same keys, same enumeration, no inherited properties), and presets the listener table with the common events, as Readable/Writable already do. Hello-world server (res.setHeader('Content-Type', ...) + res.end('Hello World')), server pinned to one core, wrk -t2 -c50 on two other physical cores, 4 interleaved rounds: req/s user µs/req sys µs/req alloc B/req main 40.9k 15.0 9.4 4374 this PR 50.0k 11.3 8.7 3905 The _events preset accounts for ~2% of that; the header container for the rest. With 8 request headers and a handler that reads two of them: 36.2k → 43.2k req/s. Responses are byte-identical. How much the dictionary-mode container costs depends on the response pattern (same harness, 2 rounds each): handler main this PR setHeader('Content-Type') + end(body) 41.7–42.4k 51.3–51.8k setHeader('Content-Type') + setHeader('Content-Length') + end(body) 47.1–49.6k 50.0–51.7k writeHead(200, { ... }) + end(body) (no setHeader(), benchmark/fixtures "normal") 46.1–50.0k 50.2–50.9k The existing benchmark/http fixtures either set Content-Length through setHeader() or pass every header to writeHead(), so they only show the smaller gains. The second commit adds a setHeaderImplicit case to http/set-header.js (res.setHeader('Content-Type', ...) + res.end(body), framing left to end()). benchmark/compare.js --runs 10 --filter set-header http: confidence improvement accuracy (*) (**) (***) http/set-header.js duration=5 res='normal' benchmarker='wrk' 2.53 % ±4.03% ±5.61% ±7.86% http/set-header.js duration=5 res='setHeader' benchmarker='wrk' ** 6.13 % ±4.03% ±5.55% ±7.61% http/set-header.js duration=5 res='setHeaderImplicit' benchmarker='wrk' *** 16.46 % ±5.10% ±7.06% ±9.78% http/set-header.js duration=5 res='setHeaderWH' benchmarker='wrk' 4.78 % ±5.76% ±7.89% ±10.75% simple.js, headers.js and incoming_headers.js are unchanged within noise. —- Ai generated, humanly reviewed.

Open Graph Description: setHeader() stored headers in a { __proto__: null } literal and OutgoingMessage let EventEmitter create the same literal for its listener table. V8 creates null-prototype literals in dictionary mod...

X Description: setHeader() stored headers in a { __proto__: null } literal and OutgoingMessage let EventEmitter create the same literal for its listener table. V8 creates null-prototype literals in dictionary mod...

Opengraph URL: https://github.com/nodejs/node/pull/66420

X: @github

direct link

Domain: github.com

react-profiling0
react-import-mapreact,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@d5750093facf
route-pattern/:user_id/:repository/pull/:id/files/:range(.:format)
route-controllerpull_requests
route-actionfiles
fetch-noncev2:f7e76eaa-17fc-6786-c1b5-c7500416742e
current-catalog-service-hashae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b
request-idDF18:1D1FA1:7CB20D:AC3AB6:6AEDCE31
html-safe-nonce625c11068e645caf0ea4e66b7617030c5cd2abf0fc33084723a81f78c0d940cf
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJERjE4OjFEMUZBMTo3Q0IyMEQ6QUMzQUI2OjZBRURDRTMxIiwidmlzaXRvcl9pZCI6IjM0MTUwMzI1OTE2NzA5NTU1NjkiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==
visitor-hmacc6da7f07a29cf18bc39bd3944f33c4675a6144e43c7278c544e7dd35c038a50f
hovercard-subject-tagpull_request:4694408962
github-keyboard-shortcutsrepository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///pull_requests/show/files
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9
twitter:imagehttps://avatars.githubusercontent.com/u/52195?s=400&v=4
twitter:cardsummary_large_image
og:imagehttps://avatars.githubusercontent.com/u/52195?s=400&v=4
og:image:altsetHeader() stored headers in a { __proto__: null } literal and OutgoingMessage let EventEmitter create the same literal for its listener table. V8 creates null-prototype literals in dictionary mod...
og:site_nameGitHub
og:typeobject
hostnamegithub.com
expected-hostnamegithub.com
Nonef60373873bb1ef795e8511ea1f2a76997e9c649d72b02942aedf2def3423a0ce
turbo-cache-controlno-preview
diff-viewunified
go-importgithub.com/nodejs/node git https://github.com/nodejs/node.git
octolytics-dimension-user_id9950313
octolytics-dimension-user_loginnodejs
octolytics-dimension-repository_id27193779
octolytics-dimension-repository_nwonodejs/node
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id27193779
octolytics-dimension-repository_network_root_nwonodejs/node
turbo-body-classeslogged-out env-production page-responsive full-width
disable-turbotrue
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release0f55cfa61438c7dc93d1024a1e5e5182b36830e2
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#start-of-content
https://github.com/
Sign inhttps://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fnodejs%2Fnode%2Fpull%2F66420%2Ffiles%2F3aacac4a3303c9c587f104d2a2553aca5a8e57b9
GitHubRepository hosting, code review, and collaborationhttps://github.com/platform
CopilotAI coding agent for tasks, projects, and automated workhttps://github.com/features/copilot
ActionsCI/CD and automationhttps://github.com/features/actions
Code QualityQuality analysis, fixes, and enforcementhttps://github.com/features/code-quality
CodespacesCloud development environmentshttps://github.com/features/codespaces
Code SecurityVulnerability detection and remediationhttps://github.com/security/advanced-security/code-security
Secret ProtectionSecret scanning and leak preventionhttps://github.com/security/advanced-security/secret-protection
All Featureshttps://github.com/features
Documentationhttps://docs.github.com/en
Traininghttps://learn.github.com/skills
Certificationshttps://learn.github.com/credentials
Build with Copilothttps://github.com/features/ai
Customize Copilothttps://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/customize-copilot-overview
Integrationshttps://github.com/marketplace
Trending reposhttps://github.com/trending
GitHub Sponsorshttps://github.com/open-source/sponsors
Developer articleshttps://github.com/resources/articles
ChangelogYour source for the latest features, improvements, and fixes across GitHub products, all in one place.https://github.blog/changelog/
Enterpriseshttps://github.com/enterprise
Teamhttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
See all industrieshttps://github.com/solutions/industry
Why GitHubhttps://github.com/why-github
Customer Storieshttps://github.com/customer-stories
Business insightshttps://github.com/solutions/executive-insights
Trust Centerhttps://github.com/trust-center
GitHub Advanced SecurityEnterprise-grade code securityhttps://github.com/security/advanced-security
Copilot for businessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Documentationhttps://docs.github.com/en
Resource centerhttps://github.com/resources
Bloghttps://github.blog/
Events & webinarshttps://github.com/resources/events
Community Forumhttps://github.com/orgs/community/discussions
Customer Storieshttps://github.com/customer-stories
Integrationshttps://github.com/marketplace
Customer supporthttps://help.github.com/
Traininghttps://learn.github.com/skills
GitHub Statushttps://www.githubstatus.com/
Abouthttps://github.com/about
Partnershttps://github.com/partners
Changeloghttps://github.blog/changelog/
GitHub UniverseThe event for developers, by developers — talks, workshops, and what’s next for GitHub.https://githubuniverse.com/
Pricinghttps://github.com/pricing
Sign inhttps://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fnodejs%2Fnode%2Fpull%2F66420%2Ffiles%2F3aacac4a3303c9c587f104d2a2553aca5a8e57b9
Sign uphttps://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fpull_requests%2Fshow%2Ffiles&source=header-repo&source_repo=nodejs%2Fnode
Reloadhttps://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9
Reloadhttps://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9
Reloadhttps://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9
nodejshttps://github.com/nodejs
nodehttps://github.com/nodejs/node
Codehttps://github.com/nodejs/node
Issues655 (655)https://github.com/nodejs/node/issues
Pull requests663 (663)https://github.com/nodejs/node/pulls
Actionshttps://github.com/nodejs/node/actions
Projectshttps://github.com/nodejs/node/projects
Security and qualityhttps://github.com/nodejs/node/security
Insightshttps://github.com/nodejs/node/pulse
Sign up for GitHub https://github.com/signup?return_to=%2Fnodejs%2Fnode%2Fissues%2Fnew%2Fchoose
terms of servicehttps://docs.github.com/terms
privacy statementhttps://docs.github.com/privacy
Sign inhttps://github.com/login?return_to=%2Fnodejs%2Fnode%2Fissues%2Fnew%2Fchoose
mcollinahttps://github.com/mcollina
nodejs:mainhttps://github.com/nodejs/node/tree/main
mcollina:http-fast-mode-objectshttps://github.com/mcollina/node/tree/http-fast-mode-objects
Conversation 5 https://github.com/nodejs/node/pull/66420
Commits 2 https://github.com/nodejs/node/pull/66420/commits
Checks 86 https://github.com/nodejs/node/pull/66420/checks
Files changed 3 https://github.com/nodejs/node/pull/66420/files
http: avoid dictionary-mode objects in responses https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#top
Show all changes 2 commits https://github.com/nodejs/node/pull/66420/files
780548c http: avoid dictionary-mode objects in responses mcollina Sep 30, 2026 https://github.com/nodejs/node/pull/66420/commits/780548ca79d70e382bf492c115abc5e8f2295fd5
3aacac4 benchmark: add implicit-framing case to http/set-header mcollina Sep 30, 2026 https://github.com/nodejs/node/pull/66420/commits/3aacac4a3303c9c587f104d2a2553aca5a8e57b9
Clear filters https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9
Please reload this pagehttps://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9
Please reload this pagehttps://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9
simple-http-server.js https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-151782908b270d89fc8261d64905936b3f479ecedaa763192d3a3efe57ad9ed7
set-header.js https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-51225ae4f750c27a05b051b5dea524b2bafcb43452c62d306e01d9bfcbbe284e
_http_outgoing.js https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-48d21edbddb6e855d1ee5716c49bcdc0d913c11ee8a24a98ea7dbc60cd253556
benchmark/fixtures/simple-http-server.jshttps://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-151782908b270d89fc8261d64905936b3f479ecedaa763192d3a3efe57ad9ed7
View file https://github.com/mcollina/node/blob/3aacac4a3303c9c587f104d2a2553aca5a8e57b9/benchmark/fixtures/simple-http-server.js
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/nodejs/node/pull/66420/files/{{ revealButtonHref }}
https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-151782908b270d89fc8261d64905936b3f479ecedaa763192d3a3efe57ad9ed7
https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-151782908b270d89fc8261d64905936b3f479ecedaa763192d3a3efe57ad9ed7
benchmark/http/set-header.jshttps://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-51225ae4f750c27a05b051b5dea524b2bafcb43452c62d306e01d9bfcbbe284e
View file https://github.com/mcollina/node/blob/3aacac4a3303c9c587f104d2a2553aca5a8e57b9/benchmark/http/set-header.js
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/nodejs/node/pull/66420/files/{{ revealButtonHref }}
https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-51225ae4f750c27a05b051b5dea524b2bafcb43452c62d306e01d9bfcbbe284e
https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-51225ae4f750c27a05b051b5dea524b2bafcb43452c62d306e01d9bfcbbe284e
https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-51225ae4f750c27a05b051b5dea524b2bafcb43452c62d306e01d9bfcbbe284e
lib/_http_outgoing.jshttps://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-48d21edbddb6e855d1ee5716c49bcdc0d913c11ee8a24a98ea7dbc60cd253556
View file https://github.com/mcollina/node/blob/3aacac4a3303c9c587f104d2a2553aca5a8e57b9/lib/_http_outgoing.js
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/nodejs/node/pull/66420/files/{{ revealButtonHref }}
https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-48d21edbddb6e855d1ee5716c49bcdc0d913c11ee8a24a98ea7dbc60cd253556
https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-48d21edbddb6e855d1ee5716c49bcdc0d913c11ee8a24a98ea7dbc60cd253556
https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-48d21edbddb6e855d1ee5716c49bcdc0d913c11ee8a24a98ea7dbc60cd253556
https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-48d21edbddb6e855d1ee5716c49bcdc0d913c11ee8a24a98ea7dbc60cd253556
https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-48d21edbddb6e855d1ee5716c49bcdc0d913c11ee8a24a98ea7dbc60cd253556
https://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9#diff-48d21edbddb6e855d1ee5716c49bcdc0d913c11ee8a24a98ea7dbc60cd253556
Please reload this pagehttps://github.com/nodejs/node/pull/66420/files/3aacac4a3303c9c587f104d2a2553aca5a8e57b9
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.