I was recently adding my Schubfach double-to-string conversion algorithm
implementation to dtoa-benchmark and noticed that std::to_chars
was notably missing from that benchmark. So I decided to add it and see how
well it compares to other methods.
And it did pretty well! This particular implementation from libc++ was 17
times faster than sprintf and almost 2 times faster than
double-conversion.
Considering that std::to_chars has been available since 2017, I think it’s
time to retire double-conversion.
There is still a considerable gap to other state-of-the-art libraries like Schubfach and Dragonbox (used in {fmt}), but performance should be more than sufficient for most use cases.
You can also clearly see that libc++ uses Ryu because their performance profiles are nearly identical, with stock implementation being just a bit faster.
The binary code is surprisingly reasonable too. For example
#include <charconv>
int main() {
char buf[25];
*std::to_chars(buf, buf + 25, 4.2).ptr = 0;
}
generates
main:
sub rsp, 40
movsd xmm0, QWORD PTR .LC0[rip]
mov rdi, rsp
lea rsi, [rsp+25]
call std::to_chars(char*, char*, double)
mov BYTE PTR [rax], 0
xor eax, eax
add rsp, 40
ret
.LC0:
.long -858993459
.long 1074842828
Godbolt: https://www.godbolt.org/z/jvahnosed
Hopefully it will remain like this, and the C++ committee resists the urge of adding wide char, locale, range and other irrelevant functionality to this low-level API.
P.S. I was surprised to see that my toy 150-line double-to-string conversion
algorithm was 15% faster than
sprintf.
Last modified on 2025-12-05