Skip to content

Speed up decimal integer parsing with SWAR - #161019

Open
kiana1kaslana wants to merge 2 commits into
rust-lang:mainfrom
kiana1kaslana:swar_int_parse
Open

Speed up decimal integer parsing with SWAR#161019
kiana1kaslana wants to merge 2 commits into
rust-lang:mainfrom
kiana1kaslana:swar_int_parse

Conversation

@kiana1kaslana

@kiana1kaslana kiana1kaslana commented Aug 13, 2026

Copy link
Copy Markdown

Speed up from_str_radix for base 10 with SWAR
Closes #87249
Process 8 decimal digits at a time using SIMD-within-a-register
instead of one digit per loop iteration. Only applies when radix
is 10 and can_not_overflow guarantees the result fits, so the
fast path needs no overflow checks.
The SWAR technique was suggested by @bormand and @Alexhuszagh in
the issue thread. Two helpers:
is_8digits(v: u64) -> bool — branch-free check that all 8
bytes are b'0'..=b'9'
parse_8digits(v: u64) -> u64 — 3 multiplications to pack 8
digits into a single value
Remaining <8 digits fall through to the existing per-digit loop.
Benchmark (stage 1, x86_64, 16-20 digit strings × 5000):
bench_u64_from_str_radix_10_long 98818 → 73194 ns (−25.9%)
bench_i64_from_str_radix_10_long 149705 → 120089 ns (−19.8%)
The mixed-input benchmark barely moves because only 2 of 19 inputs
are long enough to trigger the fast path. Added LONG_ASCII_NUMBERS
and from_str_radix_long_bench! to cover it properly.

Use SIMD-within-a-register to process 8 ASCII digits at once in
from_str_radix when radix == 10 and the result is guaranteed not to
overflow. Falls back to the existing per-digit loop for the remaining
0-7 digits.

The fast path uses two helper functions:
- is_8digits: branch-free check that all 8 bytes are b'0'..=b'9'
- parse_8digits: 3 multiplications to pack 8 digits into a u64

Benchmark on 16-20 digit decimal strings (5000 iterations, stage 1):

  bench_u64_from_str_radix_10_long   98818 -> 73194 ns  (-25.9%)
  bench_i64_from_str_radix_10_long  149705 -> 120089 ns  (-19.8%)

Also add LONG_ASCII_NUMBERS and from_str_radix_long_bench macro to
exercise the fast path with strings that trigger 2+ SWAR iterations.
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Aug 13, 2026
@rustbot

rustbot commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the pull request, and welcome! The Rust Project is excited to review your changes, and you should hear from @JohnTitor (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue
Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: libs
  • libs expanded to 12 candidates
  • Random selection from JohnTitor, Mark-Simulacrum, clarfonthey, nia-e

@rust-log-analyzer

This comment has been minimized.

Align trailing `//` comments vertically in the new benchmark data
constant. rustfmt in nightly runs during the tidy CI job flags the
misaligned comments.
Comment on lines +1844 to +1859
if radix == 10 {
while let [a, b, c, d, e, f, g, h, rest @ ..] = digits {
let chunk = u64::from_le_bytes([*a, *b, *c, *d, *e, *f, *g, *h]);
if !is_8digits(chunk) {
return Err(PIE { kind: InvalidDigit });
}
let parsed = parse_8digits(chunk) as $int_ty;
result = result * (100_000_000u32 as $int_ty);
if is_positive {
result = result + parsed;
} else {
result = result - parsed;
}
digits = rest;
}
}

@tgross35 tgross35 Aug 13, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should probably be a 32- and (maybe) 16-bit version so this doesn't wind up slower on those platforms

View changes since the review

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

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Speed up string to integer conversion too

5 participants