环境搭建与工具链:安装Rust、配置Cargo、VS Code插件推荐、第一个并发程序
好,咱们正式开始动手了。这一章说白了就是「把家伙事儿备齐」。我见过太多人卡在环境搭建这一步,其实没必要。跟着我走一遍,十分钟搞定。
安装Rust:rustup 是唯一正解
别去官网手动下载安装包,也别用系统包管理器(比如 apt、brew)。Rust 官方推荐的方式只有一个:rustup。它既是安装器,又是版本管理器,还能随时切换工具链。
核心命令:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
运行后选默认安装就行。装完记得重启终端,或者手动执行 source $HOME/.cargo/env 让环境变量生效。
验证安装:
rustc --version
cargo --version
看到版本号就对了。我个人习惯装完立刻跑一下 rustup update,确保是最新稳定版。为什么?因为 Rust 的编译错误信息一直在改进,新版能省不少排查时间。
配置Cargo:换源与项目结构
Cargo 是 Rust 的构建系统和包管理器。默认的包下载源在国外,你想想看,每次 cargo build 都要等半天下载依赖,多耽误事。所以第一步就是换源。
在 ~/.cargo/config.toml 里写入:
[source.crates-io]
replace-with = 'ustc'
[source.ustc]
registry = "sparse+https://mirrors.ustc.edu.cn/crates.io-index/"
中科大源目前是最稳的。我曾经试过其他源,偶尔会有同步延迟导致依赖解析失败,换成中科大后再没出过问题。
小技巧:如果你在公司内网,或者网络环境特殊,可以用 cargo install 安装 cargo-local-registry 做本地缓存。对于回测这种高频迭代的场景,本地缓存能省下大量重复下载时间。
VS Code插件推荐
编辑器我推荐 VS Code,不是因为它最好,而是因为生态最全。装好下面这几个插件,开发体验直接起飞:
| 插件名 | 作用 | 为什么重要 |
|---|---|---|
| rust-analyzer | 代码补全、跳转、类型提示 | Rust 类型系统复杂,没有它写起来像盲人摸象 |
| CodeLLDB | 调试器 | 并发 bug 最难查,断点调试是刚需 |
| Even Better TOML | TOML 文件语法高亮 | Cargo.toml 写多了你就知道这个多重要 |
| crates | 依赖版本检查 | 提示哪些依赖有更新,避免用旧版踩坑 |
装完 rust-analyzer 后,记得打开设置,把 rust-analyzer.cargo.allFeatures 设为 true。不然有些 crate 的特性(feature)没开启,代码提示会不全。嗯,这里要注意,很多新手会忽略这一步。
第一个并发程序:从单线程到多线程
咱们直接写一个回测场景的简化版:计算多只股票的平均收益率。单线程版本长这样:
use std::time::Instant;
fn main() {
let data = vec![
vec![0.01, 0.02, -0.01, 0.03, 0.01],
vec![0.02, -0.01, 0.03, 0.01, 0.02],
vec![0.01, 0.01, 0.02, -0.01, 0.03],
];
let start = Instant::now();
let mut results = Vec::new();
for stock in &data {
let sum: f64 = stock.iter().sum();
let avg = sum / stock.len() as f64;
results.push(avg);
}
let duration = start.elapsed();
println!("单线程耗时: {:?}", duration);
println!("结果: {:?}", results);
}
这个代码没问题,但数据量一大就慢了。咱们用 std::thread 改成并发版本:
use std::thread;
use std::time::Instant;
fn main() {
let data = vec![
vec![0.01, 0.02, -0.01, 0.03, 0.01],
vec![0.02, -0.01, 0.03, 0.01, 0.02],
vec![0.01, 0.01, 0.02, -0.01, 0.03],
];
let start = Instant::now();
let mut handles = vec![];
for stock in data {
handles.push(thread::spawn(move || {
let sum: f64 = stock.iter().sum();
sum / stock.len() as f64
}));
}
let mut results = vec![];
for handle in handles {
results.push(handle.join().unwrap());
}
let duration = start.elapsed();
println!("多线程耗时: {:?}", duration);
println!("结果: {:?}", results);
}
注意:这里用了 move 关键字把 stock 的所有权移入闭包。如果不加 move,编译器会报错——因为 Rust 无法保证线程的生命周期。我曾经在项目里忘了加 move,排查了半小时才发现,说白了就是所有权机制在并发场景下的体现。
跑一下看看,你会发现多线程版本在数据量小的时候反而可能更慢。为什么?因为线程创建和销毁有开销。但在真实回测场景中,动辄几千只股票、数万条数据,多线程的优势就出来了。
本章知识体系
下面这张图帮你理清本章的核心脉络:
说白了,这一章就是打好地基。rustup 装好、Cargo 配好、插件装全、第一个并发程序跑通,后面咱们才能放开手脚搞真正的回测加速。你想想看,如果连环境都没配好,后面讲再高深的并发技巧也是白搭。
避坑指南:我曾经在 Windows 上装 Rust 时忘了装 Visual Studio Build Tools,结果编译 C 依赖时疯狂报错。如果你用 Windows,记得先装 VC++ 生成工具,选上「使用 C++ 的桌面开发」工作负载。macOS 用户确保装了 Xcode Command Line Tools,Linux 用户确保装了 build-essential。
好了,环境搭好了,代码也跑了。接下来咱们就可以深入 Rust 的并发原语了。记住,工具只是手段,理解背后的原理才是关键。