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.

Deltas based on locally run benchmark.

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 89.25620% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.63%. Comparing base (14e16db) to head (06e2662).
⚠️ Report is 23 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 90.90% 5 Missing and 1 partial ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #62756   +/-   ##
=======================================
  Coverage   89.62%   89.63%           
=======================================
  Files         706      706           
  Lines      219136   219116   -20     
  Branches    41987    41956   -31     
=======================================
- Hits       196404   196394   -10     
+ Misses      14611    14608    -3     
+ Partials     8121     8114    -7     
Files with missing lines Coverage Δ
lib/internal/crypto/webidl.js 98.33% <90.90%> (-0.05%) ⬇️
lib/internal/crypto/util.js 95.90% <87.27%> (+0.50%) ⬆️

... and 26 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 review wanted PRs that need reviews. and removed review wanted PRs that need reviews. labels Apr 19, 2026
@panva panva marked this pull request as draft April 19, 2026 15:13
@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 panva force-pushed the webcrypto-refactors branch from cc1451b to f98babc Compare April 19, 2026 15:36
panva added 6 commits April 20, 2026 10:51
Exercise `normalizeAlgorithm`, `converters.AlgorithmIdentifier`,
`createDictionaryConverter` (with/without `[EnforceRange]` integers
and `ensureSHA` validators), and `converters.AeadParams`.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
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>
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 f98babc to 06e2662 Compare April 20, 2026 08:57
@panva
Copy link
Copy Markdown
Member Author

panva commented Apr 20, 2026

Benchmark: https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/1831

                                                                             confidence improvement accuracy (*)    (**)   (***)
crypto/webcrypto-webidl.js n=1000000 op='normalizeAlgorithm-dict'                   ***     42.11 %       ±1.72%  ±2.30%  ±3.03%
crypto/webcrypto-webidl.js n=1000000 op='normalizeAlgorithm-string'                 ***     94.83 %       ±0.50%  ±0.66%  ±0.87%
crypto/webcrypto-webidl.js n=1000000 op='webidl-algorithm-identifier-object'        ***    157.00 %      ±11.28% ±15.18% ±20.09%
crypto/webcrypto-webidl.js n=1000000 op='webidl-algorithm-identifier-string'                -1.21 %       ±5.04%  ±6.71%  ±8.74%
crypto/webcrypto-webidl.js n=1000000 op='webidl-dict-enforce-range'                 ***     39.35 %       ±0.30%  ±0.40%  ±0.52%
crypto/webcrypto-webidl.js n=1000000 op='webidl-dict-ensure-sha'                    ***     14.60 %       ±0.54%  ±0.72%  ±0.94%
crypto/webcrypto-webidl.js n=1000000 op='webidl-dict-null'                          ***     98.06 %      ±14.30% ±19.12% ±25.08%
crypto/webcrypto-webidl.js n=1000000 op='webidl-dict'                               ***     13.92 %       ±1.83%  ±2.45%  ±3.23%

@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Apr 21, 2026
@nodejs-github-bot

This comment was marked as outdated.

@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

@panva panva added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Apr 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author ready PRs that have at least one approval, no pending requests for changes, and a CI started. 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. webcrypto

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants