将Rust代码中的let移出循环是否有收益?Drop与编译输出分析
Rust代码优化相关问题解答
原始代码
use std::sync::atomic::{AtomicBool, Ordering}; fn do_something_under_lock( is_locked: &AtomicBool, ) { loop { let lock_acquired = is_locked .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) .is_ok(); if lock_acquired { // Do something // ... is_locked.store(false, Ordering::Release); break; } } }
修改后的代码(将let移出循环)
use std::sync::atomic::{AtomicBool, Ordering}; fn do_something_under_lock( is_locked: &AtomicBool, ) { let mut lock_acquired; loop { lock_acquired = is_locked .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) .is_ok(); if lock_acquired { // Do something // ... is_locked.store(false, Ordering::Release); break; } } }
针对以上代码修改,解答如下:
1. 这种修改是否能带来性能收益?
完全没有性能收益。lock_acquired是布尔值,属于栈上的基础简单类型,循环内声明和循环外声明再重复赋值,对性能的影响可以忽略不计。而且开启优化(-O)后的Rust编译器会自动识别这种场景,将变量分配优化到最优状态,两种写法在性能上无差异。
2. 由于lock_acquired的作用域看似发生变化,是否会改变Drop trait的调用时机?
不会。原因有两点:一是bool类型本身没有实现Drop trait,根本不会触发drop方法;二是就算是实现了Drop的类型,这种修改才会改变drop时机,但这里完全不涉及这个场景。
3. 编译器是否会为两段代码生成相同的机器码?
开启优化(-O)的情况下,会生成完全相同的机器码。Rust基于LLVM的后端优化会彻底忽略这种表面的作用域差异,识别出两种写法的逻辑完全一致,最终生成相同的二进制指令。
4. 查看编译器输出的最佳方式是什么?
可以通过以下几种方式:
- 生成汇编代码:使用
rustc --emit asm -O your_code.rs,会生成对应的.s汇编文件,直接查看底层指令。 - 生成LLVM中间表示:使用
rustc --emit llvm-ir -O your_code.rs,生成.ll文件,能清晰看到编译器的优化过程。 - 使用
cargo asm工具:先通过cargo install cargo-asm安装,之后用cargo asm do_something_under_lock可以直接查看目标函数的汇编代码,定位更精准。
内容的提问来源于stack exchange,提问作者user22165515
相关产品推荐
相关产品推荐

