let mut variable: Type;
loop {
variable = value;
}
or
loop {
let variable: Type = value;
}
Side note, don’t fall into the trap of premature optimization. You’ll more than likely end up shooting yourself in the foot for something that usually doesn’t matter in most cases.
Functionally equivalent, the compiler will optimize lots for you. As the programmer, your focus should be on whether that variable is relevant to the loop’s scope exclusively or not (i.e. if you need to access the variable after the loop has modified it). If not, keep it in the loop so that its easier to read your code.
Without context, there’s no reason to compare the performance of these. The compiler is complex enough that what you do in the loop and after the loop matters with regards to optimizations.
Do you have more context? What’s actually happening in the code?
I would say that they are equivalent. If I’m not mistaken,
let
statements only reserves space on the stack, and this only increments the stack register.And on the latter snippet, the compiler would certainly not bother to modify the stack pointer as the type doesn’t change.
let
statements only reserves space on the stackIt is not guaranteed to do that. It could also use a register or be optimized out completly (like in the example you posted in the other comment).
The stack pointer is also not changed for each local variable, but instead for each function call, so it wouldn’t make a difference anyway.
according to godbolt: https://rust.godbolt.org/z/hP5Y3qMPW
use rand::random; pub fn main1() { let mut var : u128; loop { var = random(); } } pub fn main2() { loop { let var : u128 = random(); } }
compiles to:
example::main1::h45edf333d7832d08: .Lfunc_begin8: sub rsp, 24 .LBB8_1: .Ltmp80: mov rax, qword ptr [rip + rand::random::he3c23ceb967a3e28@GOTPCREL] call rax mov qword ptr [rsp + 8], rdx mov qword ptr [rsp], rax jmp .LBB8_1 .Ltmp81: .Lfunc_end8: example::main2::h1a899b25b96d66db: .Lfunc_begin9: sub rsp, 24 .LBB9_1: .Ltmp82: mov rax, qword ptr [rip + rand::random::he3c23ceb967a3e28@GOTPCREL] call rax mov qword ptr [rsp + 8], rdx mov qword ptr [rsp], rax jmp .LBB9_1 .Ltmp83: .Lfunc_end9: jmp .LBB9_1
So yeah, exactly the same thing.
Fascinating! Thank you for sharing this.
The second one is more expensive as you constantly are creating a new variable. In the first one you just constantly change the value of a variable.
This is Rust not Python
They’re both optimised out by the compiler. If you disable compiler optimisations, they’re identical in machine code anyway, unless you introduce a second loop, in which case the first will be more memory efficient as the memory used in the first loop can be reused in the second loop, whereas if you declare the variable outside the loop it can’t (again, without compiler optimisations, which make the whole comparison pointless).
This is just flat out false.
That’s what I thought.