- Published on
Rust编译时与运行时代码:核心特征与实用指南
1. 编译时代码的特征
形式 | 典型场景 | 判断依据 |
---|---|---|
const 常量/函数 | const PI: f32 = 3.14; | 使用 const 关键字 |
static 静态变量 | static CONFIG: &str = "config"; | 不可变全局变量 |
属性宏 | #[derive(Debug)] | 以 #[...] 开头 |
过程宏 | serde::Serialize | 生成代码的宏 |
泛型参数 | fn<T> foo() {} | 类型在编译时确定 |
const _: () = ... | 编译时断言 | 无名常量包裹的表达式 |
include_str! 等宏 | 文件内嵌 | ! 结尾的宏 |
2. 运行时代码的特征
形式 | 典型场景 |
---|---|
fn 普通函数 | fn main() { println!(); } |
let 绑定 | let x = 1 + 1; (非常量上下文) |
match /if | 流程控制 |
trait 动态分发 | dyn Trait |
Box /Vec | 堆分配 |
网络/文件 I/O | std::fs::read |
3. 快速判断技巧
看关键字:
const
/static
→ 编译时fn
/let
→ 运行时(除非在const fn
中)
看宏调用:
- 属性宏(
#[...]
)→ 编译时 - 普通宏(
println!
)→ 运行时展开
- 属性宏(
看错误发生时机:
- 编译错误 → 编译时问题
- panic/逻辑错误 → 运行时问题
看是否依赖输入:
- 需要用户输入/网络 → 必定运行时
- 纯计算 → 可能编译时优化
4. 典型示例对比
// 编译时执行
const SQUARE: fn(i32) -> i32 = |x| x * x; // 常量函数指针
const _: () = assert!(SQUARE(2) == 4); // 编译时断言
// 运行时执行
fn main() {
let input = 3; // 运行时绑定
println!("{}", SQUARE(input)); // 运行时计算
}
5. 特殊情况
const fn
:可在编译时和运行时调用
const fn add(a: i32, b: i32) -> i32 { a + b }
const SUM: i32 = add(1, 2); // 编译时执行
let sum = add(3, 4); // 运行时执行
lazy_static
:运行时初始化,但仅一次
// lazy_static运行时初始化
lazy_static! {
static ref CONFIG: HashMap<String, String> = {
let mut m = HashMap::new();
m.insert("key".into(), "value".into());
m
};
}
const generics
:编译时确定的泛型参数(如[i32; N]
)
// 编译期泛型
fn generic_fn<T: Default>() -> T {
T::default() // 具体类型在编译时确定
}
6. agave code example
// Ensure the STORE_META_OVERHEAD constant remains accurate
const _: () = assert!(
STORE_META_OVERHEAD
== mem::size_of::<StoredMeta>()
+ mem::size_of::<AccountMeta>()
+ mem::size_of::<AccountHash>()
);
7. 实践
- 内存优化技巧
// 利用编译时布局优化Cache Line
#[repr(align(64))] // 强制缓存行对齐
struct CriticalData {
hot: [u64; 8], // 高频访问
cold: [u128; 4] // 低频数据
}
const _: () = assert!(std::mem::size_of::<CriticalData>() == 256);
- 错误处理模式
// 编译时错误码生成
macro_rules! define_errors {
($($code:ident => $msg:literal),*) => {
pub mod errors {
$(
pub const $code: (&str, u32) = ($msg, line!());
)*
}
};
}
define_errors! {
OVERFLOW => "Arithmetic overflow",
UNAUTHORIZED => "Permission denied"
}
- 零成本抽象
// 编译时策略选择
trait Backend {
const IS_GPU: bool;
fn compute() -> u64;
}
struct CpuBackend;
impl Backend for CpuBackend {
const IS_GPU: bool = false;
fn compute() -> u64 { /* CPU优化实现 */ }
}
// 根据特性选择算法
const fn select_algo<B: Backend>() -> fn() -> u64 {
if B::IS_GPU { gpu_kernel } else { cpu_kernel }
}
- 混合使用
// 可在编译时和运行时调用的函数
const fn factorial(n: u32) -> u32 {
match n {
0 | 1 => 1,
_ => n * factorial(n - 1),
}
}
fn main() {
const COMPILE_TIME: u32 = factorial(5); // 编译时计算
let runtime = factorial(10); // 运行时计算
}
THE END