Skip to content

src: use stack allocation for small string encoding#62431

Open
thisalihassan wants to merge 1 commit intonodejs:mainfrom
thisalihassan:src-string-bytes-stack-encode
Open

src: use stack allocation for small string encoding#62431
thisalihassan wants to merge 1 commit intonodejs:mainfrom
thisalihassan:src-string-bytes-stack-encode

Conversation

@thisalihassan
Copy link
Contributor

  • Introduce EncodeOneByteString / EncodeTwoByteString helper templates in StringBytes::Encode() that use a 512 byte (256-char for two-byte) stack buffer for small inputs, falling back to heap allocation + ExternString for larger ones.
  • Covers all encoding paths: ASCII, HEX, BASE64, BASE64URL, UTF8 (two-byte), and UCS2.

Refs: nodejs/performance#194

                                                                       confidence improvement accuracy (*)   (**)  (***)
buffers/buffer-base64-encode.js n=32 len=67108864                                      1.82 %       ±2.53% ±3.38% ±4.42%
buffers/buffer-base64url-encode.js n=32 len=67108864                            *     -1.70 %       ±1.39% ±1.86% ±2.42%
buffers/buffer-tostring.js n=1000000 len=1 args=0 encoding=''                 ***      3.71 %       ±1.67% ±2.23% ±2.91%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='ascii'                     0.21 %       ±2.08% ±2.78% ±3.65%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='hex'              ***     40.34 %       ±4.17% ±5.60% ±7.39%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='latin1'           ***      2.52 %       ±1.15% ±1.53% ±1.99%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='UCS-2'            ***      3.33 %       ±1.26% ±1.68% ±2.19%
buffers/buffer-tostring.js n=1000000 len=1 args=1 encoding='utf8'             ***      2.03 %       ±0.90% ±1.19% ±1.55%
buffers/buffer-tostring.js n=1000000 len=1 args=3 encoding='ascii'              *      3.00 %       ±2.83% ±3.80% ±5.02%
buffers/buffer-tostring.js n=1000000 len=1 args=3 encoding='hex'              ***     40.40 %       ±3.23% ±4.30% ±5.59%
buffers/buffer-tostring.js n=1000000 len=1 args=3 encoding='latin1'            **      2.93 %       ±2.04% ±2.73% ±3.58%
buffers/buffer-tostring.js n=1000000 len=1 args=3 encoding='UCS-2'            ***      4.55 %       ±1.17% ±1.56% ±2.04%
buffers/buffer-tostring.js n=1000000 len=1 args=3 encoding='utf8'             ***      2.52 %       ±0.88% ±1.17% ±1.52%
buffers/buffer-tostring.js n=1000000 len=1024 args=0 encoding=''                      -0.48 %       ±1.75% ±2.35% ±3.09%
buffers/buffer-tostring.js n=1000000 len=1024 args=1 encoding='ascii'                  2.68 %       ±3.68% ±4.91% ±6.44%
buffers/buffer-tostring.js n=1000000 len=1024 args=1 encoding='hex'                   -0.05 %       ±1.47% ±1.96% ±2.55%
buffers/buffer-tostring.js n=1000000 len=1024 args=1 encoding='latin1'          *      2.53 %       ±1.94% ±2.60% ±3.41%
buffers/buffer-tostring.js n=1000000 len=1024 args=1 encoding='UCS-2'                  0.75 %       ±1.80% ±2.40% ±3.13%
buffers/buffer-tostring.js n=1000000 len=1024 args=1 encoding='utf8'            *      3.19 %       ±2.47% ±3.33% ±4.40%
buffers/buffer-tostring.js n=1000000 len=1024 args=3 encoding='ascii'                  0.01 %       ±2.15% ±2.86% ±3.72%
buffers/buffer-tostring.js n=1000000 len=1024 args=3 encoding='hex'                    0.40 %       ±1.31% ±1.74% ±2.26%
buffers/buffer-tostring.js n=1000000 len=1024 args=3 encoding='latin1'          *      1.96 %       ±1.86% ±2.48% ±3.23%
buffers/buffer-tostring.js n=1000000 len=1024 args=3 encoding='UCS-2'                  0.54 %       ±1.99% ±2.65% ±3.46%
buffers/buffer-tostring.js n=1000000 len=1024 args=3 encoding='utf8'                   1.05 %       ±1.11% ±1.48% ±1.93%
buffers/buffer-tostring.js n=1000000 len=64 args=0 encoding=''                        -0.37 %       ±1.28% ±1.72% ±2.26%
buffers/buffer-tostring.js n=1000000 len=64 args=1 encoding='ascii'                   -1.33 %       ±2.21% ±2.97% ±3.92%
buffers/buffer-tostring.js n=1000000 len=64 args=1 encoding='hex'             ***     41.64 %       ±2.07% ±2.76% ±3.62%
buffers/buffer-tostring.js n=1000000 len=64 args=1 encoding='latin1'            *      1.98 %       ±1.86% ±2.48% ±3.25%
buffers/buffer-tostring.js n=1000000 len=64 args=1 encoding='UCS-2'                   -0.38 %       ±2.76% ±3.68% ±4.80%
buffers/buffer-tostring.js n=1000000 len=64 args=1 encoding='utf8'                     0.64 %       ±0.88% ±1.18% ±1.53%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='ascii'                    0.35 %       ±2.91% ±3.88% ±5.07%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='hex'             ***     40.54 %       ±1.43% ±1.90% ±2.48%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='latin1'                   1.67 %       ±2.47% ±3.30% ±4.31%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='UCS-2'                    0.32 %       ±1.93% ±2.57% ±3.35%
buffers/buffer-tostring.js n=1000000 len=64 args=3 encoding='utf8'                     0.56 %       ±0.91% ±1.21% ±1.58%

Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case, there are 35 comparisons, you can thus
expect the following amount of false-positive results:
  1.75 false positives, when considering a   5% risk acceptance (*, **, ***),
  0.35 false positives, when considering a   1% risk acceptance (**, ***),
  0.04 false positives, when considering a 0.1% risk acceptance (***)
thisalihassan@Alis-MacBook-Pro node % 

@nodejs-github-bot nodejs-github-bot added buffer Issues and PRs related to the buffer subsystem. c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. labels Mar 25, 2026
Use stack-allocated buffers in StringBytes::Encode() for small inputs
instead of heap-allocating via UncheckedMalloc for every call.

Refs: nodejs/performance#194
@thisalihassan thisalihassan force-pushed the src-string-bytes-stack-encode branch from e5fbafb to 43fd2f8 Compare March 25, 2026 11:05
@codecov
Copy link

codecov bot commented Mar 25, 2026

Codecov Report

❌ Patch coverage is 75.43860% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.69%. Comparing base (0d7e4b1) to head (43fd2f8).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/string_bytes.cc 75.43% 5 Missing and 9 partials ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #62431   +/-   ##
=======================================
  Coverage   89.68%   89.69%           
=======================================
  Files         676      676           
  Lines      206738   206748   +10     
  Branches    39594    39594           
=======================================
+ Hits       185414   185436   +22     
+ Misses      13467    13462    -5     
+ Partials     7857     7850    -7     
Files with missing lines Coverage Δ
src/string_bytes.cc 73.17% <75.43%> (+3.50%) ⬆️

... and 32 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

buffer Issues and PRs related to the buffer subsystem. c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants