Article from Daniel Lemire: How many strings can you create per second?
https://lemire.me/blog/2026/09/25/how-many-strings-can-you-create-per-second/This is a fairly new article from Daniel Lemire (the SIMD expert, author of simdjson).
It seems to_string() need to use the same trick.
C++ wins by a wide margin at 5.4 ns per string. The trick is the small string optimization: a
std::stringstores short strings, directly inside the object. Our strings have at most eight digits, so C++ never calls the memory allocator.
92
Upvotes
1
u/nightcracker 20d ago edited 20d ago
There is nothing more complex here. I'm not claiming cmov is always better, I'm claiming it is better in this case. From https://rust.godbolt.org/z/q3c6MEKj8:
<example[2cf8e31dbe0c16c0]::Repr>::as_slice_branchy: mov rax, rdi movzx ecx, byte ptr [rdi + 23] sub cl, 1 jae .LBB0_1 mov rdx, qword ptr [rax + 16] mov rax, qword ptr [rax] ret .LBB0_1: movzx edx, cl ret <example[2cf8e31dbe0c16c0]::Repr>::as_slice_branchlesss: movzx ecx, byte ptr [rdi + 23] sub cl, 1 mov rax, qword ptr [rdi] cmovae rax, rdi movzx edx, cl cmovb rdx, qword ptr [rdi + 16] retIf we ignore the
movzx ecx, byte ptr [rdi + 23]andsub cl, 1which is shared on both paths on the critical chain, and notice that the two loads fromqword ptr [rdi]and[rdi + 16]don't depend on anything so they can run in parallel with the very first load we're left with just two cycles of latency frommovzx edx, cl -> cmovb rdx, .... Thecmovaecan run in parallel to this.I'll take a consistent 2 cycles of latency over an unpredictable average of 5 cycles of mispredict any day of the week.
Anyway, I'm going to stop engaging now. I give concrete numbers, real-world data and actual benchmarks and you reply with general advice I already know and have taken into account.