Skip to content

crypto: optimize SubtleCrypto dispatch hot paths#62756

Open
panva wants to merge 6 commits intonodejs:mainfrom
panva:webcrypto-refactors
Open

crypto: optimize SubtleCrypto dispatch hot paths#62756
panva wants to merge 6 commits intonodejs:mainfrom
panva:webcrypto-refactors

Conversation

@panva
Copy link
Copy Markdown
Member

@panva panva commented Apr 15, 2026

This improves several hot paths in Web Cryptography.

Per-commit gains (each vs its parent)

crypto: optimize normalizeAlgorithm hot path

  • Replace the O(n) case-insensitive for...in loop with an O(1) SafeMap lookup pre-built at module init.
  • Hoist the { prefix, context } options object to module scope.
  • Pre-compute ObjectKeys() for simpleAlgorithmDictionaries entries at module init.
op before after Δ
normalizeAlgorithm-string 2.1 M op/s 3.8 M op/s +79%
normalizeAlgorithm-dict 679 k op/s 912 k op/s +34%

crypto: reduce allocations in WebIDL dictionary converter

  • Replace SafeArrayIterator with an index-based loop in the inner function returned by createDictionaryConverter.
  • Replace { __proto__: null, ...opts, context } with explicit property assignment when passing opts to member converters.
op before after Δ
webidl-dict 1.58 M op/s 1.62 M op/s +2.3%
webidl-dict-null 136 M op/s 219 M op/s +61%

crypto: skip string tag allocation in AlgorithmIdentifier fast path

  • Use a direct typeof check in converters.object and converters.AlgorithmIdentifier instead of the generic type() helper, which returned an intermediate 'Object' / 'Null' / ... string tag.
op before after Δ
webidl-algorithm-identifier-string 195 M op/s 195 M op/s neutral
webidl-algorithm-identifier-object 130 M op/s 278 M op/s +114%

crypto: streamline WebIDL dictionary converter hot loop

  • Classify V with typeof instead of type().
  • Hoist opts.prefix/opts.context and allMembers.length out of the loop; initialize allMembers with direct index assignment.
  • Drops the now-unused module-local type() helper.
op before after Δ
webidl-dict 1.62 M op/s 1.65 M op/s +1.6%
normalizeAlgorithm-dict 912 k op/s 936 k op/s +2.7%
webidl-dict-enforce-range 1.04 M op/s 1.08 M op/s +3.9%

crypto: reuse enforceRange option object for WebIDL integer members

  • The inline [EnforceRange] unsigned short/long/octet wrappers spread the per-member opts object into a new one solely to set enforceRange: true. Replace the 18 inline wrappers with shared helpers that mutate the caller-supplied opts in place.
op before after Δ
webidl-dict-enforce-range 1.08 M op/s 1.29 M op/s +19.7%

Cumulative

op baseline final Δ
normalizeAlgorithm-string 2.1 M op/s 3.8 M op/s +79%
normalizeAlgorithm-dict 679 k op/s 936 k op/s +38%
webidl-dict 1.58 M op/s 1.65 M op/s +5%
webidl-dict-null 136 M op/s 211 M op/s +55%
webidl-algorithm-identifier-string 197 M op/s 197 M op/s neutral
webidl-algorithm-identifier-object 130 M op/s 278 M op/s +114%
webidl-dict-enforce-range 1.05 M op/s 1.29 M op/s +23%

A benchmark is added in the first commit (benchmark/crypto/webcrypto-webidl.js) covering normalizeAlgorithm, converters.AlgorithmIdentifier, createDictionaryConverter (with/without [EnforceRange] integer members and with a null/undefined required-member fast path), and converters.AeadParams.

@panva panva added crypto Issues and PRs related to the crypto subsystem. webcrypto commit-queue-rebase Add this label to allow the Commit Queue to land a PR in several commits. labels Apr 15, 2026
@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/crypto

@nodejs-github-bot nodejs-github-bot added the needs-ci PRs that need a full CI run. label Apr 15, 2026
@panva panva force-pushed the webcrypto-refactors branch from c23467e to 62dec56 Compare April 15, 2026 13:05
@panva panva marked this pull request as draft April 15, 2026 13:16
@panva panva force-pushed the webcrypto-refactors branch from 62dec56 to 8cfb8ef Compare April 15, 2026 13:27
@panva panva marked this pull request as ready for review April 15, 2026 13:31
@panva panva changed the title crypto: optimize SubtleCrypto hot paths crypto: optimize SubtleCrypto dispatch hot paths Apr 15, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 15, 2026

Codecov Report

❌ Patch coverage is 92.50000% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.67%. Comparing base (ed05549) to head (f98babc).
⚠️ Report is 37 commits behind head on main.

Files with missing lines Patch % Lines
lib/internal/crypto/util.js 87.27% 6 Missing and 1 partial ⚠️
lib/internal/crypto/webidl.js 96.92% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #62756      +/-   ##
==========================================
- Coverage   89.69%   89.67%   -0.03%     
==========================================
  Files         706      706              
  Lines      218127   218202      +75     
  Branches    41734    41745      +11     
==========================================
+ Hits       195651   195664      +13     
- Misses      14400    14455      +55     
- Partials     8076     8083       +7     
Files with missing lines Coverage Δ
lib/internal/crypto/webidl.js 98.33% <96.92%> (-0.09%) ⬇️
lib/internal/crypto/util.js 95.90% <87.27%> (+0.38%) ⬆️

... and 58 files with indirect coverage changes

🚀 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.

@panva panva added the request-ci Add this label to start a Jenkins CI on a PR. label Apr 15, 2026
@panva panva requested a review from aduh95 April 16, 2026 09:13
@panva panva added the review wanted PRs that need reviews. label Apr 19, 2026
Exercise `normalizeAlgorithm`, `converters.AlgorithmIdentifier`,
`createDictionaryConverter` (with/without `[EnforceRange]` integers
and `ensureSHA` validators), and `converters.AeadParams`.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
@panva panva removed the review wanted PRs that need reviews. label Apr 19, 2026
@panva panva marked this pull request as draft April 19, 2026 15:13
Replace O(n) for...in loop with case-insensitive
StringPrototypeToUpperCase comparisons per algorithm
with O(1) SafeMap lookup. The map is pre-built at module
init alongside kSupportedAlgorithms.

Hoist the opts object literal used in normalizeAlgorithm
to module level to avoid allocating identical
{ prefix, context } objects on every call.

Pre-compute ObjectKeys() for simpleAlgorithmDictionaries
entries at module init to avoid allocating a new keys
array on every normalizeAlgorithm call.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
@panva panva force-pushed the webcrypto-refactors branch from 8cfb8ef to cc1451b Compare April 19, 2026 15:32
@panva panva marked this pull request as ready for review April 19, 2026 15:32
panva added 4 commits April 19, 2026 17:35
Replace SafeArrayIterator with index-based loop in the inner function
returned by createDictionaryConverter, avoiding iterator object creation
on every dictionary conversion.

Replace object spread (`{ ...opts, context }`) with explicit property
assignment when passing opts to member converters. This avoids
allocating a full spread copy per dictionary member.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Use a direct `typeof` check in `converters.object` and
`converters.AlgorithmIdentifier` instead of the generic `type()` helper,
which returned an intermediate 'Object' / 'Null' / ... string tag.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Simplify the generated dictionary converter's per-call work: classify V
with `typeof` instead of `type()`, hoist `opts.prefix`/`opts.context`
and `allMembers.length` out of the loop, and initialize `allMembers`
with direct index assignment instead of `ArrayPrototypePush`.

Also drops the now-unused `type()` helper.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
The inline `[EnforceRange] unsigned short/long/octet` wrappers spread
the per-member opts object into a new one solely to set
`enforceRange: true`. Replace the 18 inline wrappers with shared
helpers that mutate the caller-supplied opts in place.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
@panva panva force-pushed the webcrypto-refactors branch from cc1451b to f98babc Compare April 19, 2026 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commit-queue-rebase Add this label to allow the Commit Queue to land a PR in several commits. crypto Issues and PRs related to the crypto subsystem. needs-ci PRs that need a full CI run. request-ci Add this label to start a Jenkins CI on a PR. webcrypto

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants