1 编译与执行

1.1 编译型语言特性

01.编译型语言定义
    a.基本概念
        Rust是编译型语言,源代码在运行前被完全编译为机器码,无需解释器或虚拟机。
    b.优势
        a.性能优异
            直接生成机器码,运行时无额外开销。
        b.早期错误检测
            编译时捕获大部分错误,提高代码质量。
        c.无运行时依赖
            编译后的二进制文件可独立运行。

02.与其他语言对比
    a.vs解释型语言
        ---
        // Python(解释型)
        def add(a, b):
            return a + b

        // Rust(编译型)
        fn add(a: i32, b: i32) -> i32 {
            a + b
        }

        // Rust编译后直接生成机器码,Python需要解释器
        ---
    b.vs虚拟机语言
        ---
        // Java编译为字节码,运行在JVM上
        // Go有轻量级运行时和GC
        // Rust直接编译为机器码,无GC,无运行时
        ---

03.编译产物
    a.可执行文件
        ---
        // 编译生成可执行文件
        rustc main.rs
        // 生成: main (Linux/macOS) 或 main.exe (Windows)

        // 使用Cargo
        cargo build
        // 生成: target/debug/项目名

        cargo build --release
        // 生成: target/release/项目名
        ---
    b.静态库与动态库
        ---
        // 静态库
        cargo build --lib
        // 生成: target/debug/lib项目名.a (Linux/macOS)
        //      target/debug/项目名.lib (Windows)

        // 动态库
        [lib]
        crate-type = ["cdylib"]
        // 生成: lib项目名.so (Linux)
        //      lib项目名.dylib (macOS)
        //      项目名.dll (Windows)
        ---

1.2 rustc编译器

01.rustc架构
    a.编译器前端
        词法分析 → 语法分析 → 语义分析 → HIR(高级中间表示)
    b.编译器中端
        HIR → MIR(中级中间表示)→ 借用检查 → 优化
    c.编译器后端
        MIR → LLVM IR → LLVM优化 → 机器码

02.基本使用
    a.编译单文件
        ---
        // main.rs
        fn main() {
            println!("Hello, Rust!");
        }

        // 编译
        rustc main.rs
        // 运行
        ./main
        ---
    b.编译选项
        ---
        // 优化编译
        rustc -O main.rs

        // 指定输出文件名
        rustc main.rs -o myapp

        // 显示编译过程
        rustc --verbose main.rs

        // 生成汇编代码
        rustc --emit asm main.rs

        // 生成LLVM IR
        rustc --emit llvm-ir main.rs
        ---

03.编译器输出
    a.查看中间表示
        ---
        // 查看HIR
        rustc -Z unpretty=hir main.rs

        // 查看MIR
        rustc -Z unpretty=mir main.rs

        // 查看LLVM IR
        rustc --emit llvm-ir main.rs
        cat main.ll
        ---
    b.查看汇编代码
        ---
        rustc --emit asm main.rs
        cat main.s

        // 或使用cargo
        cargo rustc -- --emit asm
        ---

1.3 LLVM后端

01.LLVM作用
    a.基本概念
        LLVM是Rust的编译后端,负责将MIR转换为优化的机器码。
    b.优势
        a.跨平台支持
            支持多种CPU架构和操作系统。
        b.强大优化
            提供丰富的优化pass。
        c.成熟稳定
            被众多编译器使用,经过充分验证。

02.LLVM IR
    a.中间表示
        ---
        // Rust代码
        fn add(a: i32, b: i32) -> i32 {
            a + b
        }

        // 对应的LLVM IR(简化)
        define i32 @add(i32 %a, i32 %b) {
            %result = add i32 %a, %b
            ret i32 %result
        }
        ---
    b.查看LLVM IR
        ---
        rustc --emit llvm-ir main.rs
        cat main.ll
        ---

03.目标平台
    a.查看支持的目标
        ---
        rustc --print target-list
        // 输出: x86_64-unknown-linux-gnu
        //      aarch64-apple-darwin
        //      wasm32-unknown-unknown
        //      等数百个目标
        ---
    b.指定目标平台
        ---
        // 交叉编译到Windows
        rustc --target x86_64-pc-windows-gnu main.rs

        // 编译到WebAssembly
        rustc --target wasm32-unknown-unknown main.rs
        ---

1.4 编译流程:源码到机器码

01.完整编译流程
    a.词法分析
        源代码 → Token流
    b.语法分析
        Token流 → AST(抽象语法树)
    c.语义分析
        AST → HIR(高级中间表示)
    d.类型检查
        HIR → 类型推导和检查
    e.借用检查
        HIR → MIR → 借用检查器验证
    f.优化
        MIR → 优化后的MIR
    g.代码生成
        MIR → LLVM IR → 机器码

02.示例代码编译
    a.源代码
        ---
        fn factorial(n: u32) -> u32 {
            if n == 0 {
                1
            } else {
                n * factorial(n - 1)
            }
        }

        fn main() {
            let result = factorial(5);
            println!("5! = {}", result);
        }
        ---
    b.编译过程
        ---
        // 1. 编译并查看各阶段输出
        rustc main.rs

        // 2. 查看MIR
        rustc -Z unpretty=mir main.rs > main.mir

        // 3. 查看LLVM IR
        rustc --emit llvm-ir main.rs

        // 4. 查看汇编
        rustc --emit asm main.rs

        // 5. 生成可执行文件
        rustc -O main.rs
        ---

03.编译时间分析
    a.查看编译时间
        ---
        cargo build --timings
        // 生成编译时间报告
        ---
    b.并行编译
        ---
        // Cargo默认并行编译
        cargo build -j 4  // 使用4个线程
        ---

1.5 增量编译

01.增量编译原理
    a.基本概念
        只重新编译修改过的代码和受影响的依赖,加快编译速度。
    b.工作机制
        Rust编译器跟踪代码变化,缓存未修改部分的编译结果。

02.启用增量编译
    a.Cargo配置
        ---
        // Cargo.toml
        [profile.dev]
        incremental = true  // 默认开启

        [profile.release]
        incremental = true  // release模式也可开启
        ---
    b.环境变量
        ---
        export CARGO_INCREMENTAL=1
        cargo build
        ---

03.增量编译效果
    a.首次编译
        ---
        cargo clean
        time cargo build
        // 首次编译: 30秒
        ---
    b.增量编译
        ---
        // 修改一个文件
        time cargo build
        // 增量编译: 3秒
        ---

04.清理增量缓存
    a.清理命令
        ---
        cargo clean
        // 或只清理增量缓存
        rm -rf target/debug/incremental
        ---

1.6 交叉编译

01.交叉编译概念
    a.基本定义
        在一个平台上编译出另一个平台的可执行文件。
    b.应用场景
        在Linux上编译Windows程序、在x86上编译ARM程序等。

02.安装目标平台
    a.添加目标
        ---
        // 查看已安装目标
        rustup target list --installed

        // 添加Windows目标
        rustup target add x86_64-pc-windows-gnu

        // 添加ARM目标
        rustup target add aarch64-unknown-linux-gnu

        // 添加WebAssembly目标
        rustup target add wasm32-unknown-unknown
        ---

03.交叉编译示例
    a.编译到Windows
        ---
        cargo build --target x86_64-pc-windows-gnu
        // 生成: target/x86_64-pc-windows-gnu/debug/项目名.exe
        ---
    b.编译到ARM
        ---
        cargo build --target aarch64-unknown-linux-gnu
        ---
    c.编译到WebAssembly
        ---
        cargo build --target wasm32-unknown-unknown
        ---

04.配置链接器
    a.Cargo配置
        ---
        // .cargo/config.toml
        [target.x86_64-pc-windows-gnu]
        linker = "x86_64-w64-mingw32-gcc"

        [target.aarch64-unknown-linux-gnu]
        linker = "aarch64-linux-gnu-gcc"
        ---

1.7 编译优化级别

01.优化级别
    a.debug模式
        ---
        cargo build
        // 优化级别: 0
        // 特点: 编译快,包含调试信息,性能较低
        ---
    b.release模式
        ---
        cargo build --release
        // 优化级别: 3
        // 特点: 编译慢,高度优化,性能最佳
        ---

02.自定义优化
    a.Cargo配置
        ---
        // Cargo.toml
        [profile.dev]
        opt-level = 0  // 0-3

        [profile.release]
        opt-level = 3
        lto = true     // 链接时优化
        codegen-units = 1  // 单个代码生成单元
        ---
    b.优化级别对比
        ---
        // opt-level = 0: 无优化,快速编译
        // opt-level = 1: 基本优化
        // opt-level = 2: 较多优化
        // opt-level = 3: 最大优化
        // opt-level = "s": 优化大小
        // opt-level = "z": 极致优化大小
        ---

03.性能对比
    a.编译时间vs运行性能
        ---
        // debug模式
        cargo build
        time ./target/debug/myapp
        // 编译: 5秒,运行: 10秒

        // release模式
        cargo build --release
        time ./target/release/myapp
        // 编译: 30秒,运行: 1秒
        ---

2 内存管理

2.1 所有权系统

01.所有权规则
    a.三大规则
        a.每个值都有一个所有者
            ---
            let s = String::from("hello");
            // s是字符串的所有者
            ---
        b.同一时间只能有一个所有者
            ---
            let s1 = String::from("hello");
            let s2 = s1;  // 所有权转移
            // s1不再有效
            ---
        c.所有者离开作用域时,值被丢弃
            ---
            {
                let s = String::from("hello");
            }  // s离开作用域,内存被释放
            ---

02.所有权转移
    a.移动语义
        ---
        fn main() {
            let s1 = String::from("hello");
            let s2 = s1;  // 移动,s1失效
            
            // println!("{}", s1);  // 错误!
            println!("{}", s2);  // 正确
        }
        ---
    b.克隆
        ---
        let s1 = String::from("hello");
        let s2 = s1.clone();  // 深拷贝
        
        println!("{}, {}", s1, s2);  // 都有效
        ---

03.Copy trait
    a.栈上类型
        ---
        let x = 5;
        let y = x;  // 复制,x仍然有效
        
        println!("{}, {}", x, y);  // 都有效
        // 整数实现了Copy trait
        ---

2.2 栈与堆

01.栈内存
    a.特点
        快速分配,自动管理,大小固定,LIFO顺序。
    b.栈上数据
        ---
        fn main() {
            let x = 5;        // 栈上
            let y = true;     // 栈上
            let z = 3.14;     // 栈上
        }
        ---

02.堆内存
    a.特点
        动态分配,手动管理(Rust自动化),大小可变。
    b.堆上数据
        ---
        fn main() {
            let s = String::from("hello");  // 堆上
            let v = vec![1, 2, 3];          // 堆上
            let b = Box::new(5);            // 堆上
        }
        ---

03.性能对比
    a.栈分配
        ---
        fn stack_alloc() {
            let arr = [0; 1000];  // 栈上数组
        }
        ---
    b.堆分配
        ---
        fn heap_alloc() {
            let vec = vec![0; 1000];  // 堆上向量
        }
        ---

2.3 借用检查器

01.借用规则
    a.不可变借用
        ---
        let s = String::from("hello");
        let r1 = &s;  // 不可变借用
        let r2 = &s;  // 可以有多个
        println!("{}, {}", r1, r2);
        ---
    b.可变借用
        ---
        let mut s = String::from("hello");
        let r = &mut s;  // 可变借用
        r.push_str(", world");
        // 同一时间只能有一个可变借用
        ---

02.借用检查
    a.编译时检查
        ---
        let mut s = String::from("hello");
        let r1 = &s;
        let r2 = &mut s;  // 错误!不能同时存在
        ---
    b.生命周期
        ---
        fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
            if x.len() > y.len() { x } else { y }
        }
        ---

03.悬垂引用
    a.编译器防止
        ---
        fn dangle() -> &String {
            let s = String::from("hello");
            &s  // 错误!返回悬垂引用
        }  // s被释放
        ---

2.4 生命周期

01.生命周期概念
    a.基本定义
        引用的有效作用域,确保引用始终有效。
    b.生命周期标注
        ---
        fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
            if x.len() > y.len() { x } else { y }
        }
        ---

02.生命周期省略
    a.省略规则
        ---
        // 编译器自动推导
        fn first_word(s: &str) -> &str {
            &s[..1]
        }
        
        // 等价于
        fn first_word<'a>(s: &'a str) -> &'a str {
            &s[..1]
        }
        ---

03.结构体生命周期
    a.生命周期标注
        ---
        struct ImportantExcerpt<'a> {
            part: &'a str,
        }
        
        fn main() {
            let novel = String::from("Call me Ishmael.");
            let first_sentence = novel.split('.').next().unwrap();
            let i = ImportantExcerpt {
                part: first_sentence,
            };
        }
        ---

2.5 内存布局

01.数据布局
    a.基本类型
        ---
        use std::mem;
        
        fn main() {
            println!("i32: {} bytes", mem::size_of::<i32>());
            println!("i64: {} bytes", mem::size_of::<i64>());
            println!("&i32: {} bytes", mem::size_of::<&i32>());
        }
        ---
    b.结构体布局
        ---
        struct Point {
            x: i32,
            y: i32,
        }
        
        println!("Point: {} bytes", mem::size_of::<Point>());
        // 输出: 8 bytes
        ---

02.内存对齐
    a.对齐规则
        ---
        #[repr(C)]
        struct Foo {
            a: u8,   // 1 byte
            b: u32,  // 4 bytes
            c: u16,  // 2 bytes
        }
        // 总大小: 12 bytes (含填充)
        ---

03.零大小类型
    a.ZST示例
        ---
        struct Unit;
        println!("Unit: {} bytes", mem::size_of::<Unit>());
        // 输出: 0 bytes
        ---

2.6 Drop trait与析构

01.Drop trait
    a.自动析构
        ---
        struct Resource {
            name: String,
        }
        
        impl Drop for Resource {
            fn drop(&mut self) {
                println!("Dropping {}", self.name);
            }
        }
        
        fn main() {
            let r = Resource {
                name: String::from("resource"),
            };
        }  // 自动调用drop
        ---

02.手动释放
    a.drop函数
        ---
        let r = Resource {
            name: String::from("resource"),
        };
        drop(r);  // 提前释放
        // r不再可用
        ---

03.RAII模式
    a.资源管理
        ---
        use std::fs::File;
        
        fn main() {
            let f = File::open("file.txt").unwrap();
            // 使用文件
        }  // 文件自动关闭
        ---

2.7 内存安全保证

01.编译时保证
    a.无空指针
        Rust没有null,使用Option<T>。
    b.无悬垂指针
        借用检查器防止悬垂引用。
    c.无数据竞争
        所有权系统防止并发数据竞争。

02.运行时检查
    a.边界检查
        ---
        let v = vec![1, 2, 3];
        let x = v[10];  // panic! 运行时检查
        ---
    b.整数溢出
        ---
        let x: u8 = 255;
        let y = x + 1;  // debug模式panic
        ---

03.unsafe代码
    a.unsafe块
        ---
        unsafe {
            let p = 0x1234 as *const i32;
            // 解引用原始指针
        }
        ---

3 运行时

3.1 最小运行时

01.运行时概念
    a.Rust运行时
        Rust几乎没有运行时,只有最小的启动代码。
    b.对比其他语言
        无GC、无虚拟机、无重量级运行时。

02.启动代码
    a.程序入口
        ---
        fn main() {
            println!("Hello");
        }
        ---

03.零成本抽象
    a.示例
        ---
        let sum: i32 = (1..=100).sum();
        ---

3.2 程序启动流程

01.启动过程
    a.入口点
        操作系统 → _start → main
    b.初始化
        设置栈、初始化全局变量。

02.查看启动代码
    a.反汇编
        ---
        cargo build
        objdump -d target/debug/myapp
        ---

3.3 标准库运行时

01.标准库初始化
    a.全局分配器
        默认使用系统分配器。

02.运行时组件
    a.panic处理
        ---
        use std::panic;
        
        fn main() {
            panic::set_hook(Box::new(|info| {
                println!("Panic: {:?}", info);
            }));
        }
        ---

3.4 panic机制

01.panic触发
    a.显式panic
        ---
        panic!("Error!");
        ---

02.panic处理
    a.捕获panic
        ---
        use std::panic;
        
        let result = panic::catch_unwind(|| {
            panic!("test");
        });
        ---

3.5 栈展开与abort

01.栈展开
    a.默认行为
        panic时展开栈,调用析构函数。

02.abort模式
    a.配置
        ---
        [profile.release]
        panic = 'abort'
        ---

3.6 全局分配器

01.默认分配器
    a.系统分配器
        ---
        use std::alloc::System;
        
        #[global_allocator]
        static GLOBAL: System = System;
        ---

02.自定义分配器
    a.实现GlobalAlloc
        ---
        use std::alloc::{GlobalAlloc, Layout};
        ---

3.7 no_std环境

01.no_std概念
    a.不使用标准库
        ---
        #![no_std]
        #![no_main]
        ---

02.嵌入式开发
    a.目标平台
        ---
        rustup target add thumbv7em-none-eabihf
        ---

4 底层机制

4.1 零成本抽象

01.零成本原则
    a.定义
        抽象不应带来运行时开销。
    b.示例
        ---
        let sum: i32 = (1..=100).sum();
        ---

02.泛型单态化
    a.编译时展开
        ---
        fn add<T>(a: T, b: T) -> T {
            a + b
        }
        ---

4.2 单态化

01.单态化概念
    a.泛型展开
        编译时为每个具体类型生成专门代码。

02.代码膨胀
    a.二进制大小
        泛型函数会为每个类型生成代码。

4.3 内联优化

01.内联标记
    a.inline属性
        ---
        #[inline]
        fn add(a: i32, b: i32) -> i32 {
            a + b
        }
        ---

02.编译器优化
    a.自动内联
        编译器自动内联小函数。

4.4 vtable与动态分发

01.trait对象
    a.动态分发
        ---
        trait Animal {
            fn speak(&self);
        }
        
        fn make_sound(animal: &dyn Animal) {
            animal.speak();
        }
        ---

02.vtable结构
    a.虚函数表
        trait对象包含数据指针和vtable指针。

4.5 FFI外部函数接口

01.调用C函数
    a.extern声明
        ---
        extern "C" {
            fn abs(x: i32) -> i32;
        }
        
        fn main() {
            unsafe {
                println!("{}", abs(-3));
            }
        }
        ---

02.导出Rust函数
    a.no_mangle
        ---
        #[no_mangle]
        pub extern "C" fn rust_fn(x: i32) -> i32 {
            x * 2
        }
        ---

4.6 内联汇编

01.asm!宏
    a.基本使用
        ---
        use std::arch::asm;
        
        fn main() {
            let x: u64;
            unsafe {
                asm!("mov {}, 5", out(reg) x);
            }
            println!("x = {}", x);
        }
        ---

02.寄存器操作
    a.输入输出
        ---
        let mut x: u64 = 1;
        unsafe {
            asm!("add {0}, {1}", inout(reg) x, in(reg) 5);
        }
        ---

4.7 unsafe与原始指针

01.unsafe块
    a.五种unsafe操作
        解引用原始指针、调用unsafe函数、访问可变静态变量等。

02.原始指针
    a.创建和使用
        ---
        let mut x = 5;
        let raw = &mut x as *mut i32;
        
        unsafe {
            *raw = 10;
        }
        println!("x = {}", x);
        ---

03.安全抽象
    a.封装unsafe
        ---
        pub fn safe_fn(x: i32) -> i32 {
            unsafe {
                // unsafe操作
            }
        }
        ---

5 性能与调试

5.1 性能分析:perf、flamegraph

01.perf工具
    a.性能采样
        ---
        cargo build --release
        perf record ./target/release/myapp
        perf report
        ---

02.flamegraph
    a.生成火焰图
        ---
        cargo install flamegraph
        cargo flamegraph
        ---

03.性能分析
    a.热点函数
        ---
        perf top
        ---

5.2 内存分析:valgrind、heaptrack

01.valgrind
    a.内存检查
        ---
        cargo build
        valgrind ./target/debug/myapp
        ---

02.heaptrack
    a.堆分析
        ---
        heaptrack ./target/release/myapp
        ---

03.内存泄漏检测
    a.Rust内存安全
        Rust通常不会内存泄漏,除非使用Rc循环引用。

5.3 调试工具:gdb、lldb

01.gdb调试
    a.基本使用
        ---
        cargo build
        gdb ./target/debug/myapp
        
        (gdb) break main
        (gdb) run
        (gdb) next
        ---

02.lldb调试
    a.macOS调试
        ---
        lldb ./target/debug/myapp
        
        (lldb) breakpoint set --name main
        (lldb) run
        ---

03.调试信息
    a.Cargo配置
        ---
        [profile.release]
        debug = true
        ---

5.4 基准测试:criterion

01.criterion使用
    a.添加依赖
        ---
        [dev-dependencies]
        criterion = "0.5"
        
        [[bench]]
        name = "my_benchmark"
        harness = false
        ---
    b.编写测试
        ---
        use criterion::{black_box, criterion_group, criterion_main, Criterion};
        
        fn fibonacci(n: u64) -> u64 {
            match n {
                0 => 1,
                1 => 1,
                n => fibonacci(n-1) + fibonacci(n-2),
            }
        }
        
        fn criterion_benchmark(c: &mut Criterion) {
            c.bench_function("fib 20", |b| {
                b.iter(|| fibonacci(black_box(20)))
            });
        }
        
        criterion_group!(benches, criterion_benchmark);
        criterion_main!(benches);
        ---

02.运行基准测试
    a.执行
        ---
        cargo bench
        ---

5.5 编译时计算:const fn

01.const fn定义
    a.编译时函数
        ---
        const fn add(a: i32, b: i32) -> i32 {
            a + b
        }
        
        const RESULT: i32 = add(2, 3);
        ---

02.const泛型
    a.编译时泛型
        ---
        fn array<const N: usize>() -> [i32; N] {
            [0; N]
        }
        
        let arr = array::<10>();
        ---

03.性能优势
    a.零运行时开销
        编译时完成计算,运行时直接使用结果。

5.6 链接时优化:LTO

01.LTO配置
    a.启用LTO
        ---
        [profile.release]
        lto = true
        // 或
        lto = "thin"
        ---

02.优化效果
    a.性能提升
        完整LTO: 最大优化,编译慢。thin LTO: 平衡优化和编译速度。

03.代码生成单元
    a.配置
        ---
        [profile.release]
        codegen-units = 1
        ---

5.7 Profile-Guided Optimization

01.PGO概念
    a.基于运行时数据优化
        先运行程序收集数据,再用数据指导优化。

02.使用PGO
    a.步骤
        ---
        // 1. 生成instrumented版本
        RUSTFLAGS="-Cprofile-generate=/tmp/pgo-data" cargo build --release
        
        // 2. 运行程序收集数据
        ./target/release/myapp
        
        // 3. 使用数据重新编译
        RUSTFLAGS="-Cprofile-use=/tmp/pgo-data" cargo build --release
        ---

03.性能提升
    a.优化效果
        根据实际运行路径优化,通常可提升5-15%性能。