Use std::from_chars instead of stoll/stoull in string2int.h#9007
Merged
Conversation
07849e3 to
cf082cb
Compare
std::from_chars instead of stoll/stoull in string2int.h
peterschrammel
approved these changes
May 11, 2026
53ac489 to
f40c8cf
Compare
Replace the exception-based stoll/stoull implementation of string2optional<T> with std::from_chars. This eliminates exception-handling overhead and locale indirection, yielding 88-184x speedup in microbenchmarks. Benchmark results (1.4M conversions, mix of valid/invalid inputs, -O2 clang++): signed long long: stoll 1424 ms vs from_chars 8.9 ms (161x) unsigned long long: stoull 968 ms vs from_chars 10.2 ms ( 95x) int: stoll 1446 ms vs from_chars 7.9 ms (184x) unsigned long long hex: stoull 497 ms vs from_chars 5.7 ms ( 88x) Semantic changes: - Leading whitespace is no longer silently skipped. std::stoll/stoull skip leading whitespace; std::from_chars does not. In this codebase, inputs to string2optional are identifiers and numeric literals from the IR, which never have leading whitespace, so this is not a behavioral change in practice. - The old code converted via long long then narrowed (throwing out_of_range on overflow). The new code uses from_chars directly with the target type, which returns errc::result_out_of_range on overflow. The observable behavior (returning nullopt on overflow) is identical.
f40c8cf to
9e2a3a7
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #9007 +/- ##
===========================================
+ Coverage 80.55% 80.56% +0.01%
===========================================
Files 1707 1707
Lines 189016 189047 +31
Branches 73 73
===========================================
+ Hits 152261 152308 +47
+ Misses 36755 36739 -16 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replace the exception-based
std::stoll/std::stoullimplementation ofstring2optional<T>withstd::from_chars(C++17). This removes three template functions (string2optional_basex2,wrap_string_conversion) and replaces them with a single, simpler template.Benchmark Results
1.4M conversions (mix of valid/invalid inputs),
-O2clang++ on macOS:signed long longunsigned long longint(with narrowing)unsigned long long(base 16)The large speedup comes from: (1) no exception throw/catch on invalid inputs, (2) no locale overhead that stoll/stoull carry.
Semantic Changes
Leading whitespace:
std::stoll/stoullsilently skip leading whitespace;std::from_charsdoes not. In this codebase, inputs tostring2optionalare numeric literals and identifiers from the IR which never have leading whitespace, so this is not a behavioral change in practice.Overflow handling: The old code converted via
long longthen narrowed (throwingout_of_rangeon overflow, caught bywrap_string_conversion). The new code usesfrom_charsdirectly with the target typeT, which returnserrc::result_out_of_range. The observable behavior (returningnullopt) is identical.Partial parses: Both old and new reject strings that are not fully consumed (old via
stollsemantics + narrow check, new viaptr != lastcheck). The new version is actually stricter —stoll("123abc")would parse123successfully, whilefrom_charswith theptr != lastcheck returnsnullopt.