Skip to content

crypto: optimize normalizeAlgorithm dispatch hot path#62756

Closed
panva wants to merge 2 commits intonodejs:mainfrom
panva:webcrypto-refactors
Closed

crypto: optimize normalizeAlgorithm dispatch hot path#62756
panva wants to merge 2 commits intonodejs:mainfrom
panva:webcrypto-refactors

Conversation

@panva
Copy link
Copy Markdown
Member

@panva panva commented Apr 15, 2026

Replace the O(n) case-insensitive algorithm-name scan with an O(1) SafeMap lookup. The map is pre-built at module init alongside kSupportedAlgorithms.

Use null-prototype objects for the generated operation tables and cached dictionary metadata so these internal lookups never consult Object.prototype. This causes a severe performance regression.

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.


Replace object spread in nested WebIDL conversion options with stable-shape ordinary objects. This keeps hot dictionary and sequence conversion paths from allocating null-prototype spread results.

Apply the same pattern to Web Crypto converter wrappers that override allowResizable or enable [EnforceRange].

@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 93.84615% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.67%. Comparing base (e0200f2) to head (17a9267).
⚠️ Report is 23 commits behind head on main.

Files with missing lines Patch % Lines
lib/internal/crypto/util.js 87.71% 6 Missing and 1 partial ⚠️
lib/internal/webidl.js 96.87% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #62756      +/-   ##
==========================================
- Coverage   89.69%   89.67%   -0.02%     
==========================================
  Files         712      712              
  Lines      221273   221300      +27     
  Branches    42392    42386       -6     
==========================================
- Hits       198473   198457      -16     
- Misses      14634    14671      +37     
- Partials     8166     8172       +6     
Files with missing lines Coverage Δ
lib/internal/crypto/webidl.js 99.35% <100.00%> (+0.01%) ⬆️
lib/internal/webidl.js 99.44% <96.87%> (+<0.01%) ⬆️
lib/internal/crypto/util.js 96.97% <87.71%> (+0.46%) ⬆️

... and 53 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 2 times, most recently from f98babc to 06e2662 Compare April 20, 2026 08:57
@panva

This comment was marked as outdated.

@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

This comment was marked as outdated.

@panva panva added author ready PRs that have at least one approval, no pending requests for changes, and a CI started. review wanted PRs that need reviews. labels Apr 21, 2026
@panva panva marked this pull request as draft April 26, 2026 10:03
@panva panva removed review wanted PRs that need reviews. author ready PRs that have at least one approval, no pending requests for changes, and a CI started. labels May 4, 2026
@panva panva force-pushed the webcrypto-refactors branch 2 times, most recently from 3c42258 to 6ab9ee9 Compare May 4, 2026 15:52
@panva panva changed the title crypto: optimize SubtleCrypto dispatch hot paths crypto: optimize normalizeAlgorithm dispatch hot path May 4, 2026
@panva panva added performance Issues and PRs related to the performance of Node.js. and removed commit-queue-rebase Add this label to allow the Commit Queue to land a PR in several commits. labels May 4, 2026
@panva panva marked this pull request as ready for review May 4, 2026 15:53
@panva panva added the review wanted PRs that need reviews. label May 4, 2026
@panva panva force-pushed the webcrypto-refactors branch from 6ab9ee9 to 47714a5 Compare May 4, 2026 15:58
Replace the O(n) case-insensitive algorithm-name scan
with an 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 47714a5 to 292bebd Compare May 4, 2026 16:36
Replace object spread in nested WebIDL conversion
options with stable-shape ordinary objects. This keeps
hot dictionary and sequence conversion paths from
allocating null-prototype spread results.

Apply the same pattern to Web Crypto converter wrappers
that override allowResizable or enable [EnforceRange].

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
@panva panva added the commit-queue-rebase Add this label to allow the Commit Queue to land a PR in several commits. label May 4, 2026
@panva
Copy link
Copy Markdown
Member Author

panva commented May 4, 2026

With only the first commit:

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

                                                                           confidence improvement accuracy (*)   (**)   (***)
misc/webcrypto-webidl.js n=1000000 op='normalizeAlgorithm-dict'                   ***     64.05 %       ±3.60% ±4.82%  ±6.34%
misc/webcrypto-webidl.js n=1000000 op='normalizeAlgorithm-string'                 ***    164.69 %       ±2.27% ±3.04%  ±3.98%
misc/webcrypto-webidl.js n=1000000 op='webidl-algorithm-identifier-object'                -0.43 %       ±4.16% ±5.53%  ±7.21%
misc/webcrypto-webidl.js n=1000000 op='webidl-algorithm-identifier-string'                -1.70 %       ±6.44% ±8.57% ±11.15%
misc/webcrypto-webidl.js n=1000000 op='webidl-dict-enforce-range'                         -1.01 %       ±1.65% ±2.21%  ±2.90%
misc/webcrypto-webidl.js n=1000000 op='webidl-dict-ensure-sha'                             1.23 %       ±3.18% ±4.23%  ±5.52%
misc/webcrypto-webidl.js n=1000000 op='webidl-dict-null'                                   0.42 %       ±2.46% ±3.27%  ±4.26%
misc/webcrypto-webidl.js n=1000000 op='webidl-dict'                                 *     -2.32 %       ±2.10% ±2.81%  ±3.69%

With both commits:

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

                                                                                         confidence improvement accuracy (*)    (**)   (***)
misc/webcrypto-webidl.js n=1000000 op='normalizeAlgorithm-dict'                                 ***    194.86 %       ±0.88%  ±1.17%  ±1.52%
misc/webcrypto-webidl.js n=1000000 op='normalizeAlgorithm-string'                               ***    479.28 %       ±6.94%  ±9.35% ±12.40%
misc/webcrypto-webidl.js n=1000000 op='webidl-algorithm-identifier-object'                               2.99 %       ±4.42%  ±5.89%  ±7.67%
misc/webcrypto-webidl.js n=1000000 op='webidl-algorithm-identifier-string'                              -3.32 %       ±7.10%  ±9.44% ±12.29%
misc/webcrypto-webidl.js n=1000000 op='webidl-dict-enforce-range'                               ***    708.45 %       ±8.80% ±11.86% ±15.74%
misc/webcrypto-webidl.js n=1000000 op='webidl-dict-ensure-sha'                                  ***    119.44 %       ±2.77%  ±3.70%  ±4.84%
misc/webcrypto-webidl.js n=1000000 op='webidl-dict-null'                                          *     -2.83 %       ±2.55%  ±3.40%  ±4.42%
misc/webcrypto-webidl.js n=1000000 op='webidl-dict'                                             ***    392.81 %       ±5.83%  ±7.83% ±10.35%
misc/webidl-buffer-source.js n=1000000 input='arraybuffer'                                              -0.79 %       ±6.02%  ±8.01% ±10.43%
misc/webidl-buffer-source.js n=1000000 input='bigint64array'                                            -1.95 %       ±3.61%  ±4.80%  ±6.26%
misc/webidl-buffer-source.js n=1000000 input='biguint64array'                                           -0.48 %       ±5.87%  ±7.81% ±10.17%
misc/webidl-buffer-source.js n=1000000 input='buffer'                                                    4.02 %       ±6.73%  ±8.96% ±11.67%
misc/webidl-buffer-source.js n=1000000 input='dataview'                                                  0.26 %       ±4.87%  ±6.48%  ±8.44%
misc/webidl-buffer-source.js n=1000000 input='float16array'                                             -2.07 %       ±5.64%  ±7.55%  ±9.92%
misc/webidl-buffer-source.js n=1000000 input='float32array'                                              2.25 %       ±4.01%  ±5.33%  ±6.94%
misc/webidl-buffer-source.js n=1000000 input='float64array'                                              0.15 %       ±4.53%  ±6.03%  ±7.85%
misc/webidl-buffer-source.js n=1000000 input='int16array'                                                1.64 %       ±6.27%  ±8.38% ±11.00%
misc/webidl-buffer-source.js n=1000000 input='int32array'                                               -1.22 %       ±3.59%  ±4.78%  ±6.22%
misc/webidl-buffer-source.js n=1000000 input='int8array'                                                -3.88 %       ±3.93%  ±5.24%  ±6.83%
misc/webidl-buffer-source.js n=1000000 input='uint16array'                                              -1.56 %       ±5.58%  ±7.44%  ±9.70%
misc/webidl-buffer-source.js n=1000000 input='uint32array'                                               3.82 %       ±4.74%  ±6.32%  ±8.24%
misc/webidl-buffer-source.js n=1000000 input='uint8array'                                                2.09 %       ±3.88%  ±5.17%  ±6.74%
misc/webidl-buffer-source.js n=1000000 input='uint8clampedarray'                                         0.57 %       ±6.30%  ±8.40% ±10.96%
misc/webidl-convert-to-int.js n=1000000 input='clamp' converter='byte'                                   0.55 %       ±3.67%  ±4.89%  ±6.37%
misc/webidl-convert-to-int.js n=1000000 input='clamp' converter='long long'                             -2.35 %       ±2.78%  ±3.71%  ±4.84%
misc/webidl-convert-to-int.js n=1000000 input='clamp' converter='octet'                                 -1.07 %       ±2.65%  ±3.53%  ±4.59%
misc/webidl-convert-to-int.js n=1000000 input='clamp' converter='unsigned long'                          0.99 %       ±2.24%  ±2.99%  ±3.89%
misc/webidl-convert-to-int.js n=1000000 input='clamp' converter='unsigned short'                        -0.22 %       ±2.16%  ±2.88%  ±3.75%
misc/webidl-convert-to-int.js n=1000000 input='enforce-range' converter='byte'                           0.80 %       ±1.63%  ±2.17%  ±2.82%
misc/webidl-convert-to-int.js n=1000000 input='enforce-range' converter='long long'                      0.89 %       ±1.62%  ±2.16%  ±2.82%
misc/webidl-convert-to-int.js n=1000000 input='enforce-range' converter='octet'                         -0.46 %       ±2.35%  ±3.13%  ±4.09%
misc/webidl-convert-to-int.js n=1000000 input='enforce-range' converter='unsigned long'                 -0.58 %       ±1.98%  ±2.63%  ±3.43%
misc/webidl-convert-to-int.js n=1000000 input='enforce-range' converter='unsigned short'                -0.78 %       ±2.30%  ±3.06%  ±3.98%
misc/webidl-convert-to-int.js n=1000000 input='fractional' converter='byte'                              0.05 %       ±4.46%  ±5.97%  ±7.81%
misc/webidl-convert-to-int.js n=1000000 input='fractional' converter='long long'                        -1.33 %       ±2.78%  ±3.70%  ±4.82%
misc/webidl-convert-to-int.js n=1000000 input='fractional' converter='octet'                            -0.03 %       ±2.22%  ±2.95%  ±3.84%
misc/webidl-convert-to-int.js n=1000000 input='fractional' converter='unsigned long'                    -0.08 %       ±1.49%  ±1.98%  ±2.58%
misc/webidl-convert-to-int.js n=1000000 input='fractional' converter='unsigned short'                   -1.57 %       ±4.49%  ±6.00%  ±7.86%
misc/webidl-convert-to-int.js n=1000000 input='integer' converter='byte'                                -1.31 %       ±3.13%  ±4.19%  ±5.50%
misc/webidl-convert-to-int.js n=1000000 input='integer' converter='long long'                           -0.27 %       ±2.35%  ±3.13%  ±4.09%
misc/webidl-convert-to-int.js n=1000000 input='integer' converter='octet'                                1.85 %       ±3.62%  ±4.86%  ±6.43%
misc/webidl-convert-to-int.js n=1000000 input='integer' converter='unsigned long'                       -0.63 %       ±3.03%  ±4.05%  ±5.32%
misc/webidl-convert-to-int.js n=1000000 input='integer' converter='unsigned short'                      -1.56 %       ±3.68%  ±4.92%  ±6.45%
misc/webidl-convert-to-int.js n=1000000 input='object' converter='byte'                                 -1.79 %       ±2.72%  ±3.62%  ±4.71%
misc/webidl-convert-to-int.js n=1000000 input='object' converter='long long'                            -0.95 %       ±1.99%  ±2.65%  ±3.44%
misc/webidl-convert-to-int.js n=1000000 input='object' converter='octet'                                 0.43 %       ±2.33%  ±3.10%  ±4.04%
misc/webidl-convert-to-int.js n=1000000 input='object' converter='unsigned long'                         0.29 %       ±1.97%  ±2.62%  ±3.41%
misc/webidl-convert-to-int.js n=1000000 input='object' converter='unsigned short'                        0.03 %       ±2.52%  ±3.36%  ±4.38%
misc/webidl-convert-to-int.js n=1000000 input='wrap' converter='byte'                                    1.40 %       ±4.41%  ±5.87%  ±7.65%
misc/webidl-convert-to-int.js n=1000000 input='wrap' converter='long long'                               1.73 %       ±1.76%  ±2.35%  ±3.06%
misc/webidl-convert-to-int.js n=1000000 input='wrap' converter='octet'                                  -3.02 %       ±4.19%  ±5.57%  ±7.25%
misc/webidl-convert-to-int.js n=1000000 input='wrap' converter='unsigned long'                          -0.10 %       ±4.44%  ±5.91%  ±7.70%
misc/webidl-convert-to-int.js n=1000000 input='wrap' converter='unsigned short'                         -1.54 %       ±4.61%  ±6.14%  ±7.99%

@nodejs-github-bot

This comment was marked as outdated.

@panva panva added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label May 4, 2026
@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

@panva panva added the commit-queue Add this label to land a pull request using GitHub Actions. label May 6, 2026
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label May 6, 2026
@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

Landed in e80b5d2...fa17dc2

nodejs-github-bot pushed a commit that referenced this pull request May 6, 2026
Replace the O(n) case-insensitive algorithm-name scan
with an 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>
PR-URL: #62756
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
nodejs-github-bot pushed a commit that referenced this pull request May 6, 2026
Replace object spread in nested WebIDL conversion
options with stable-shape ordinary objects. This keeps
hot dictionary and sequence conversion paths from
allocating null-prototype spread results.

Apply the same pattern to Web Crypto converter wrappers
that override allowResizable or enable [EnforceRange].

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
PR-URL: #62756
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
@panva panva deleted the webcrypto-refactors branch May 6, 2026 13:01
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. performance Issues and PRs related to the performance of Node.js. review wanted PRs that need reviews. webcrypto

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants