Skip to content

Conversation

slagiewka
Copy link
Contributor

Description

Instead of asking the global namespace for it every time, store the reference and put access it faster each time it's used.

Comparing to the published server v0.10.5 with #2383 reverted. I reverted it because even though removing of the WeakMap improves performance, the other changes make it dunk. When I picked changes from #1505 (and ended with the same approach as #2383 without removing public API), it was 3-5% faster.

Fastify benchmarks against node:http.

┌──────────────────────────┬─────────┬────────┬────────────┬──────────────┬───────────────┐
│                          │ Version │ Router │ Requests/s │ Latency (ms) │ Throughput/Mb │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ node-http                │ v24.0.1 │ ✗      │ 61911.2    │ 15.66        │ 11.04         │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ whatwg-node-server-local │ 0.10.5  │ ✗      │ 54320.0    │ 17.91        │ 9.69          │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ whatwg-node-server       │ 0.10.5  │ ✗      │ 52256.8    │ 18.62        │ 9.32          │
└──────────────────────────┴─────────┴────────┴────────────┴──────────────┴───────────────┘

many runs, actually:

┌──────────────────────────┬─────────┬────────┬────────────┬──────────────┬───────────────┐
│                          │ Version │ Router │ Requests/s │ Latency (ms) │ Throughput/Mb │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ node-http                │ v24.0.1 │ ✗      │ 62528.8    │ 15.48        │ 11.15         │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ whatwg-node-server-local │ 0.10.5  │ ✗      │ 54447.2    │ 17.86        │ 9.71          │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ whatwg-node-server       │ 0.10.5  │ ✗      │ 52801.6    │ 18.45        │ 9.42          │
└──────────────────────────┴─────────┴────────┴────────────┴──────────────┴───────────────┘

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as
    expected)
  • This change requires a documentation update

Screenshots/Sandbox (if appropriate/relevant):

n/a

Checklist:

  • I have followed the
    CONTRIBUTING doc and the
    style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests and linter rules pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Further comments

This change based on current master:

┌──────────────────────────┬─────────┬────────┬────────────┬──────────────┬───────────────┐
│                          │ Version │ Router │ Requests/s │ Latency (ms) │ Throughput/Mb │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ node-http                │ v24.0.1 │ ✗      │ 61268.0    │ 15.83        │ 10.93         │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ whatwg-node-server       │ 0.10.5  │ ✗      │ 51875.2    │ 18.78        │ 9.25          │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ whatwg-node-server-local │ 0.10.5  │ ✗      │ 49934.4    │ 19.52        │ 8.90          │
└──────────────────────────┴─────────┴────────┴────────────┴──────────────┴───────────────┘

Just master vs published v0.10.5:

┌──────────────────────────┬─────────┬────────┬────────────┬──────────────┬───────────────┐
│                          │ Version │ Router │ Requests/s │ Latency (ms) │ Throughput/Mb │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ node-http                │ v24.0.1 │ ✗      │ 63389.2    │ 15.27        │ 11.30         │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ whatwg-node-server       │ 0.10.5  │ ✗      │ 53907.2    │ 18.06        │ 9.61          │
├──────────────────────────┼─────────┼────────┼────────────┼──────────────┼───────────────┤
│ whatwg-node-server-local │ 0.10.5  │ ✗      │ 49610.4    │ 19.66        │ 8.85          │
└──────────────────────────┴─────────┴────────┴────────────┴──────────────┴───────────────┘

Instead of asking the global namespace for it every time, store the
reference and put access it faster each time it's used.
Copy link
Contributor

coderabbitai bot commented May 10, 2025

📝 Walkthrough

Summary by CodeRabbit

  • Chores
    • Updated internal tracking for fake promises to use a standardized symbol, ensuring more consistent internal handling.
    • Added a changeset to document this patch update for improved version tracking.

Walkthrough

The update introduces a new changeset documenting a patch for @whatwg-node/promise-helpers and refactors the internal mechanism for tagging fake promises. The string-based symbol lookup is replaced with a single, centralized symbol constant, standardizing how fake promises are identified within the module.

Changes

File(s) Change Summary
.changeset/cruel-colts-show.md Added a changeset file documenting a patch update for symbol reuse in fake promise handling.
packages/promise-helpers/src/index.ts Refactored fake promise tagging to use a centralized symbol constant instead of a string key.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant PromiseHelpers

    Caller->>PromiseHelpers: fakePromise()
    PromiseHelpers->>PromiseHelpers: Tag with kFakePromise symbol
    Caller->>PromiseHelpers: isFakePromise(obj)
    PromiseHelpers->>PromiseHelpers: Check for kFakePromise symbol
    Caller->>PromiseHelpers: fakeRejectPromise()
    PromiseHelpers->>PromiseHelpers: Tag with kFakePromise symbol
    Caller->>PromiseHelpers: isFakeRejectPromise(obj)
    PromiseHelpers->>PromiseHelpers: Check for kFakePromise symbol
Loading

Possibly related PRs

  • Upcoming Release Changes #2184: The main PR refactors the internal symbol used to tag fake promises in @whatwg-node/promise-helpers, while the retrieved PR updates fakePromise to accept MaybePromise and renames functions in iterateAsync; both modify fakePromise but focus on different internal aspects, making them related.

Poem

In the land of promises, symbols now unite,
No more stringy secrets hidden out of sight.
A single sign for fakes, so easy to discern,
Patch noted and logged, for all who yearn.
🐇✨

Tip

⚡️ Faster reviews with caching
  • CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.

Enjoy the performance boost—your workflow just got faster.

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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)
.changeset/cruel-colts-show.md (1)

5-5: Enhance changeset summary style
To follow conventional-commit and changeset conventions, consider prefixing with a type/scope (e.g., perf(promise-helpers):) and using lowercase for consistency:

- Reuse fake promise Symbol
+ perf(promise-helpers): reuse fake promise symbol
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d754a7e and 84349ff.

📒 Files selected for processing (2)
  • .changeset/cruel-colts-show.md (1 hunks)
  • packages/promise-helpers/src/index.ts (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: unit / node 18
  • GitHub Check: unit / node 20
  • GitHub Check: unit / node 23
  • GitHub Check: unit / node 22
  • GitHub Check: unit / deno
  • GitHub Check: unit / bun
  • GitHub Check: node-fetch (consumeBody)
  • GitHub Check: server (native)
🔇 Additional comments (4)
packages/promise-helpers/src/index.ts (4)

4-4: Centralize and cache the fake-promise symbol lookup
Great improvement: caching the result of Symbol.for avoids repeated global lookups and standardizes the tag across the module.


92-93: Consistently tag resolved fake promises
Adding [kFakePromise]: 'resolved' ensures every fake-resolved promise carries the same identifier for later detection.


200-201: Consistently tag rejected fake promises
Adding [kFakePromise]: 'rejected' mirrors the resolved case and makes error‐path promises discoverable via the same symbol.


317-323: Use the cached symbol in detection helpers
Refactoring both isFakePromise and isFakeRejectPromise to rely on kFakePromise aligns with the new tagging approach and removes string-based lookups.

@ardatan
Copy link
Owner

ardatan commented May 10, 2025

Thanks for the PR but I actually didn't do anything with promise helpers in my PR.
You can see the diff;
https://github.com/ardatan/whatwg-node/pull/2383/files
Also the merged PR has not been published yet

@ardatan ardatan merged commit d86b4f3 into ardatan:master May 10, 2025
20 checks passed
Copy link
Contributor Author

@slagiewka slagiewka left a comment

Choose a reason for hiding this comment

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

Thanks for the PR but I actually didn't do anything with promise helpers in my PR.

I'm aware. I'm just pointing it out, that in order to explain that this particular change may make it slightly faster, I need to compare against something earlier. Otherwise it would seems as if I made it slower 🙂

Copy link
Contributor

@benchmarks/server results (undici)

     ✓ no-errors
     ✓ expected-result

   ✓ checks.........................: 100.00% ✓ 218656      ✗ 0     
     data_received..................: 22 MB   733 kB/s
     data_sent......................: 8.7 MB  292 kB/s
     http_req_blocked...............: avg=1.43µs   min=922ns    med=1.21µs   max=302.91µs p(90)=1.91µs   p(95)=2.08µs  
     http_req_connecting............: avg=1ns      min=0s       med=0s       max=123.34µs p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=211.13µs min=157.12µs med=199.04µs max=60.43ms  p(90)=226.36µs p(95)=235.95µs
       { expected_response:true }...: avg=211.13µs min=157.12µs med=199.04µs max=60.43ms  p(90)=226.36µs p(95)=235.95µs
     http_req_failed................: 0.00%   ✓ 0           ✗ 109328
     http_req_receiving.............: avg=25.54µs  min=14.6µs   med=23.36µs  max=4.44ms   p(90)=31.09µs  p(95)=33.95µs 
     http_req_sending...............: avg=6.35µs   min=4.14µs   med=5.5µs    max=154.22µs p(90)=8.15µs   p(95)=8.86µs  
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=179.23µs min=126.9µs  med=167.29µs max=60.36ms  p(90)=190.85µs p(95)=199.44µs
     http_reqs......................: 109328  3644.145812/s
     iteration_duration.............: avg=269.95µs min=200.62µs med=256.69µs max=60.58ms  p(90)=287.68µs p(95)=299.91µs
     iterations.....................: 109328  3644.145812/s
     vus............................: 1       min=1         max=1   
     vus_max........................: 1       min=1         max=1   

Copy link
Contributor

@benchmarks/server results (native)

     ✓ no-errors
     ✓ expected-result

   ✓ checks.........................: 100.00% ✓ 232230      ✗ 0     
     data_received..................: 23 MB   778 kB/s
     data_sent......................: 9.3 MB  310 kB/s
     http_req_blocked...............: avg=1.46µs   min=932ns    med=1.22µs   max=266.68µs p(90)=1.94µs   p(95)=2.11µs  
     http_req_connecting............: avg=1ns      min=0s       med=0s       max=139.29µs p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=195.07µs min=144.99µs med=184.6µs  max=9.51ms   p(90)=211.27µs p(95)=220.82µs
       { expected_response:true }...: avg=195.07µs min=144.99µs med=184.6µs  max=9.51ms   p(90)=211.27µs p(95)=220.82µs
     http_req_failed................: 0.00%   ✓ 0           ✗ 116115
     http_req_receiving.............: avg=25.52µs  min=13.92µs  med=23.19µs  max=2.91ms   p(90)=31.09µs  p(95)=33.77µs 
     http_req_sending...............: avg=6.45µs   min=4.08µs   med=5.64µs   max=1.58ms   p(90)=8.15µs   p(95)=8.9µs   
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=163.09µs min=116.16µs med=152.52µs max=9.45ms   p(90)=176.03µs p(95)=184.77µs
     http_reqs......................: 116115  3870.361168/s
     iteration_duration.............: avg=253.9µs  min=191.61µs med=242.63µs max=9.6ms    p(90)=272.19µs p(95)=284.11µs
     iterations.....................: 116115  3870.361168/s
     vus............................: 1       min=1         max=1   
     vus_max........................: 1       min=1         max=1   

Copy link
Contributor

@benchmarks/node-fetch results (noConsumeBody)

   ✓ active_handles.................: avg=140.616445 min=33      med=141     max=191      p(90)=160     p(95)=165    
     data_received..................: 21 MB  713 kB/s
     data_sent......................: 14 MB  462 kB/s
     http_req_blocked...............: avg=3.56µs     min=641ns   med=1.44µs  max=5.15ms   p(90)=2.05µs  p(95)=2.34µs 
     http_req_connecting............: avg=1.78µs     min=0s      med=0s      max=5.08ms   p(90)=0s      p(95)=0s     
     http_req_duration..............: avg=21.38ms    min=2.07ms  med=20.82ms max=961.78ms p(90)=26.82ms p(95)=28.21ms
       { expected_response:true }...: avg=21.38ms    min=2.07ms  med=20.82ms max=961.78ms p(90)=26.82ms p(95)=28.21ms
     http_req_failed................: 0.00%  ✓ 0           ✗ 139882
     http_req_receiving.............: avg=33.66µs    min=9.39µs  med=23.48µs max=24.2ms   p(90)=38.21µs p(95)=44.44µs
     http_req_sending...............: avg=11.23µs    min=3.34µs  med=6.53µs  max=15.03ms  p(90)=9.73µs  p(95)=13.75µs
     http_req_tls_handshaking.......: avg=0s         min=0s      med=0s      max=0s       p(90)=0s      p(95)=0s     
     http_req_waiting...............: avg=21.33ms    min=2.04ms  med=20.78ms max=961.67ms p(90)=26.78ms p(95)=28.16ms
     http_reqs......................: 139882 4662.103206/s
     iteration_duration.............: avg=42.87ms    min=15.75ms med=41.42ms max=984.44ms p(90)=46.08ms p(95)=52.17ms
     iterations.....................: 69917  2330.251711/s
     vus............................: 100    min=100       max=100 
     vus_max........................: 100    min=100       max=100 

Copy link
Contributor

@benchmarks/node-fetch results (consumeBody)

   ✓ active_handles.................: avg=140.135718 min=12     med=140     max=189     p(90)=161     p(95)=163    
     data_received..................: 20 MB  668 kB/s
     data_sent......................: 13 MB  428 kB/s
     http_req_blocked...............: avg=2.44µs     min=641ns  med=1.23µs  max=4.57ms  p(90)=2.01µs  p(95)=2.22µs 
     http_req_connecting............: avg=574ns      min=0s     med=0s      max=4.44ms  p(90)=0s      p(95)=0s     
     http_req_duration..............: avg=22.84ms    min=2.59ms med=22.25ms max=1.16s   p(90)=28.55ms p(95)=30.02ms
       { expected_response:true }...: avg=22.84ms    min=2.59ms med=22.25ms max=1.16s   p(90)=28.55ms p(95)=30.02ms
     http_req_failed................: 0.00%  ✓ 0           ✗ 130936
     http_req_receiving.............: avg=32.67µs    min=9.4µs  med=23.83µs max=12.07ms p(90)=37.68µs p(95)=43.12µs
     http_req_sending...............: avg=10.62µs    min=3.42µs med=5.86µs  max=17.44ms p(90)=9.64µs  p(95)=12.5µs 
     http_req_tls_handshaking.......: avg=0s         min=0s     med=0s      max=0s      p(90)=0s      p(95)=0s     
     http_req_waiting...............: avg=22.79ms    min=2.55ms med=22.21ms max=1.16s   p(90)=28.51ms p(95)=29.97ms
     http_reqs......................: 130936 4364.043605/s
     iteration_duration.............: avg=45.78ms    min=9.76ms med=44.18ms max=1.18s   p(90)=48.59ms p(95)=55.29ms
     iterations.....................: 65452  2181.488529/s
     vus............................: 46     min=46        max=100 
     vus_max........................: 100    min=100       max=100 

Copy link
Contributor

@benchmarks/server results (ponyfill)

     ✓ no-errors
     ✓ expected-result

   ✓ checks.........................: 100.00% ✓ 293356      ✗ 0     
     data_received..................: 29 MB   963 kB/s
     data_sent......................: 12 MB   391 kB/s
     http_req_blocked...............: avg=1.38µs   min=852ns    med=1.16µs   max=641.83µs p(90)=1.85µs   p(95)=2.04µs  
     http_req_connecting............: avg=3ns      min=0s       med=0s       max=582.51µs p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=140.75µs min=95.78µs  med=135.85µs max=5.85ms   p(90)=158.6µs  p(95)=165.7µs 
       { expected_response:true }...: avg=140.75µs min=95.78µs  med=135.85µs max=5.85ms   p(90)=158.6µs  p(95)=165.7µs 
     http_req_failed................: 0.00%   ✓ 0           ✗ 146678
     http_req_receiving.............: avg=25.01µs  min=12.1µs   med=23.29µs  max=2.74ms   p(90)=30.74µs  p(95)=33.57µs 
     http_req_sending...............: avg=6.48µs   min=4.1µs    med=5.66µs   max=287.14µs p(90)=8.25µs   p(95)=9.1µs   
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=109.26µs min=68.6µs   med=104.07µs max=5.64ms   p(90)=123.59µs p(95)=129.63µs
     http_reqs......................: 146678  4888.831719/s
     iteration_duration.............: avg=199.87µs min=141.27µs med=194.36µs max=6.05ms   p(90)=220.26µs p(95)=229.52µs
     iterations.....................: 146678  4888.831719/s
     vus............................: 1       min=1         max=1   
     vus_max........................: 1       min=1         max=1   

@slagiewka slagiewka deleted the reuse_fake_promise_symbol branch May 10, 2025 12:46
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.

2 participants