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
@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 84.90566% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.71%. Comparing base (0d7e4b1) to head (73eb342).
⚠️ Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
src/string_bytes.cc 84.90% 1 Missing and 7 partials ⚠️
Additional details and impacted files
@@ Coverage Diff @@ ## main #62431 +/- ## ========================================== + Coverage 89.68% 89.71% +0.02%  ========================================== Files 676 678 +2 Lines 206738 207201 +463 Branches 39594 39728 +134 ========================================== + Hits 185414 185883 +469  + Misses 13467 13422 -45  - Partials 7857 7896 +39 
Files with missing lines Coverage Δ
src/string_bytes.cc 74.63% <84.90%> (+4.96%) ⬆️

... and 67 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.
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 43fd2f8 to 73eb342 Compare March 27, 2026 12:26
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.

3 participants