Skip to content

websocket: 200x faster generate mask#3204

Merged
tsctx merged 10 commits into
nodejs:mainfrom
tsctx:websocket/improve-performance-of-generate-mask
May 7, 2024
Merged

websocket: 200x faster generate mask#3204
tsctx merged 10 commits into
nodejs:mainfrom
tsctx:websocket/improve-performance-of-generate-mask

Conversation

@tsctx

@tsctx tsctx commented May 5, 2024

Copy link
Copy Markdown
Member

The disadvantage is increased memory usage.

benchmark                  time (avg)             (min … max)       p75       p99      p999
------------------------------------------------------------- -----------------------------
• generate
------------------------------------------------------------- -----------------------------
generateMask            15.69 ns/iter      (9.77 ns … 332 ns)  15.14 ns  72.66 ns    180 ns
crypto.randomBytes(4)   3'874 ns/iter   (2'971 ns … 6'260 ns)  4'528 ns  6'086 ns  6'260 ns

summary for generate
  generateMask
   246.99x faster than crypto.randomBytes(4)

@tsctx tsctx force-pushed the websocket/improve-performance-of-generate-mask branch from d5a1a46 to 25c9ceb Compare May 5, 2024 11:05
@codecov-commenter

codecov-commenter commented May 5, 2024

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 73.33333% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.16%. Comparing base (9f26aff) to head (720e8d7).
⚠️ Report is 793 commits behind head on main.

Files with missing lines Patch % Lines
lib/web/websocket/frame.js 73.33% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3204      +/-   ##
==========================================
- Coverage   94.19%   94.16%   -0.03%     
==========================================
  Files          90       90              
  Lines       24492    24513      +21     
==========================================
+ Hits        23070    23083      +13     
- Misses       1422     1430       +8     

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

@tsctx tsctx force-pushed the websocket/improve-performance-of-generate-mask branch from 3145947 to 61fd2e8 Compare May 5, 2024 11:22
@metcoder95 metcoder95 requested a review from KhafraDev May 5, 2024 11:28
Comment thread lib/web/websocket/frame.js Outdated
Comment thread lib/web/websocket/frame.js Outdated
@ronag

ronag commented May 5, 2024

Copy link
Copy Markdown
Member

You don't actually need the mask. You can just use a 0 mask. It's only necessary for browsers.

@ronag

ronag commented May 5, 2024

Copy link
Copy Markdown
Member

I open end an issue for this over at ws some time ago.

@KhafraDev

Copy link
Copy Markdown
Member

You don't actually need the mask. You can just use a 0 mask. It's only necessary for browsers.

WebSocket is a browser spec, but it's also part of the RFC ;)

   The masking key is a 32-bit value chosen at random by the client.
   When preparing a masked frame, the client MUST pick a fresh masking
   key from the set of allowed 32-bit values.  The masking key needs to
   be unpredictable

@ronag

ronag commented May 5, 2024

Copy link
Copy Markdown
Member

Just saying. That's one place you could deviate and gain significant performance with no practical side effects. A zero mask is a noop when applied.

@KhafraDev

Copy link
Copy Markdown
Member

I don't disagree that masking is pretty much useless, but I'd prefer to follow the spec at least until WebSocket is mature. Even then I'd prefer if it was opt-in behavior, similar to ws iirc, maybe via a WebSocketDispatcher or similar.

@Uzlopak Uzlopak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Comment thread lib/web/websocket/frame.js Outdated
Comment thread lib/web/websocket/frame.js Outdated
tsctx and others added 2 commits May 6, 2024 05:52
Co-authored-by: Aras Abbasi <aras.abbasi@googlemail.com>
@tsctx

tsctx commented May 5, 2024

Copy link
Copy Markdown
Member Author

@mcollina ptal

Comment thread lib/web/websocket/frame.js
@tsctx

tsctx commented May 7, 2024

Copy link
Copy Markdown
Member Author

@mcollina ptal

Comment thread lib/web/websocket/frame.js Outdated
@github-actions github-actions Bot mentioned this pull request May 7, 2024
@lpinca

lpinca commented May 18, 2024

Copy link
Copy Markdown
Member

I think that using a non-cryptographically strong random number generator by default is not a wise decision.

  1. It violates the specification (the RFC, not the WHATWG spec) that all implementations should follow.
  2. It completely defeats the point of masking. Using a 0 mask is more or less the same.
  3. It is true that the user has full control over the bytes that are sent over the wire when using the client programmatically, but the client (Node.js) might be embedded in applications that run in the end user devices and that work exactly like a browser.

ws moved in the opposite direction a long time ago (websockets/ws#832).

Be prepared to receive security disclosures about this or add documentation to prevent them.

@tsctx

tsctx commented May 18, 2024

Copy link
Copy Markdown
Member Author

Non-encrypted random number generation is for fallback when there is no cryptographic module.
By default, encrypted secure random number generation is performed.

@lpinca

lpinca commented May 18, 2024

Copy link
Copy Markdown
Member

Oh, sorry, I did not notice that. Out of curiosity, when is the crypto module not used?

@tsctx

tsctx commented May 18, 2024

Copy link
Copy Markdown
Member Author

@lpinca

lpinca commented May 18, 2024

Copy link
Copy Markdown
Member

Ok, it's from the Node.js build. I thought undici did something special.

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.

8 participants