I'm new to Rust and I wonder if any "string-interpolation
method" is faster.
let var = "World";
println!("Hello {}", var);
println!("Hello {var}");
format!("{argument}", argument = "test");
Is there even any observable difference?
Since these macros are converted into Rust source code at compile-time
, whereby each argument interacts with a formatter
, it probably gets optimized away, right?
I wonder about positional parameters
and named parameters
in particular.
"Hello {}", var
, "Hello {var}"
and "Hello {argument}", argument = var
will compile to the exact same bytecode.
Note that this is not just an optimization, this is guaranteed to be done at compile time because all three generate the same Arguments object that gets passed on to the the internal print implementation.
pub fn foo(var: u32){
println!("Hello {}", var);
}
pub fn bar(var: u32){
println!("Hello {var}");
}
pub fn baz(var: u32){
println!("Hello {argument}", argument = var);
}
example::foo:
sub rsp, 72
mov dword ptr [rsp + 4], edi
lea rax, [rsp + 4]
mov qword ptr [rsp + 8], rax
mov rax, qword ptr [rip + core::fmt::num::imp::<impl core::fmt::Display for u32>::fmt@GOTPCREL]
mov qword ptr [rsp + 16], rax
lea rax, [rip + .Lanon.460b7f3ee3193f887017359a1e30dfa7.2]
mov qword ptr [rsp + 24], rax
mov qword ptr [rsp + 32], 2
mov qword ptr [rsp + 56], 0
lea rax, [rsp + 8]
mov qword ptr [rsp + 40], rax
mov qword ptr [rsp + 48], 1
lea rdi, [rsp + 24]
call qword ptr [rip + std::io::stdio::_print@GOTPCREL]
add rsp, 72
ret
example::bar:
sub rsp, 72
mov dword ptr [rsp + 4], edi
lea rax, [rsp + 4]
mov qword ptr [rsp + 8], rax
mov rax, qword ptr [rip + core::fmt::num::imp::<impl core::fmt::Display for u32>::fmt@GOTPCREL]
mov qword ptr [rsp + 16], rax
lea rax, [rip + .Lanon.460b7f3ee3193f887017359a1e30dfa7.2]
mov qword ptr [rsp + 24], rax
mov qword ptr [rsp + 32], 2
mov qword ptr [rsp + 56], 0
lea rax, [rsp + 8]
mov qword ptr [rsp + 40], rax
mov qword ptr [rsp + 48], 1
lea rdi, [rsp + 24]
call qword ptr [rip + std::io::stdio::_print@GOTPCREL]
add rsp, 72
ret
example::baz:
sub rsp, 72
mov dword ptr [rsp + 4], edi
lea rax, [rsp + 4]
mov qword ptr [rsp + 8], rax
mov rax, qword ptr [rip + core::fmt::num::imp::<impl core::fmt::Display for u32>::fmt@GOTPCREL]
mov qword ptr [rsp + 16], rax
lea rax, [rip + .Lanon.460b7f3ee3193f887017359a1e30dfa7.2]
mov qword ptr [rsp + 24], rax
mov qword ptr [rsp + 32], 2
mov qword ptr [rsp + 56], 0
lea rax, [rsp + 8]
mov qword ptr [rsp + 40], rax
mov qword ptr [rsp + 48], 1
lea rdi, [rsp + 24]
call qword ptr [rip + std::io::stdio::_print@GOTPCREL]
add rsp, 72
ret
.Lanon.460b7f3ee3193f887017359a1e30dfa7.0:
.ascii "Hello "
.Lanon.460b7f3ee3193f887017359a1e30dfa7.1:
.byte 10
.Lanon.460b7f3ee3193f887017359a1e30dfa7.2:
.quad .Lanon.460b7f3ee3193f887017359a1e30dfa7.0
.asciz "\006\000\000\000\000\000\000"
.quad .Lanon.460b7f3ee3193f887017359a1e30dfa7.1
.asciz "\001\000\000\000\000\000\000"
format
, however, does something completely different. So comparing it in regards of performance doesn't make much sense. Although when comparing different ways of how format
can be used, the same reasoning applies to it as well, of course.