cschuman/cargo-perf

GitHub: cschuman/cargo-perf

一款 Rust 静态分析工具,用于检测 clippy 遗漏的异步正确性缺陷和性能反面模式。

Stars: 3 | Forks: 0

# cargo-perf **针对 Rust 中 async 正确性和运行时性能的静态分析。** [![Crates.io](https://img.shields.io/crates/v/cargo-perf.svg)](https://crates.io/crates/cargo-perf) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/cschuman/cargo-perf/actions/workflows/ci.yml) [![License](https://img.shields.io/crates/l/cargo-perf.svg)](LICENSE) ## 问题所在 这些 bug 能够正常编译并发布到生产环境: ``` // Blocks the async runtime — causes timeouts under load async fn read_config() -> Config { let data = std::fs::read_to_string("config.toml").unwrap(); toml::from_str(&data).unwrap() } // Deadlock risk — a *synchronous* guard held across an await point async fn update(mutex: &std::sync::Mutex) { let guard = mutex.lock().unwrap(); some_async_op().await; // sync guard held across .await can deadlock the runtime } // 737x slower — regex compilation in hot loop for line in lines { if Regex::new(r"\d+").unwrap().is_match(line) { ... } } ``` cargo-perf 能够捕获所有这些问题。 ## 安装说明 通过 [`cargo-binstall`](https://github.com/cargo-bins/cargo-binstall) 安装预编译二进制文件(最快 — 无需编译): ``` cargo binstall cargo-perf ``` 或者从源码构建: ``` cargo install cargo-perf ``` 无论哪种方式,二进制文件都会安装为 `cargo-perf`,因此它作为 cargo 子命令运行:`cargo perf`。 **在现有代码库中采用?** 不要让已有的问题阻碍你 — 请参阅 [快速入门](docs/getting-started.md) 了解基准与渐进式(baseline-and-ratchet)工作流,该工作流仅在有*新*问题时导致 CI 失败。 ## 用法 ``` cargo perf # Analyze current directory cargo perf --strict # High-confidence rules only (CI recommended) cargo perf --strict --fail-on error # Fail CI on issues cargo perf --format sarif # For GitHub Code Scanning cargo perf fix --dry-run # Preview auto-fixes cargo perf fix # Apply auto-fixes ``` ## 规则 ### 错误(高置信度) | 规则 | 捕获内容 | |------|-----------------| | `async-block-in-async` | 异步函数中的 `std::fs`、`thread::sleep` 和阻塞式 I/O | | `lock-across-await` | **同步** `MutexGuard`/`RwLockGuard` (std/parking_lot) 跨越 `.await` 持有 — 存在死锁风险 | | `n-plus-one-query` | 循环内的数据库查询 (SQLx, Diesel, SeaORM) | ### 警告(中等置信度) | 规则 | 捕获内容 | 影响 | |------|-----------------|--------| | `unbounded-channel` | `mpsc::channel()`, `unbounded_channel()` | 内存耗尽 | | `unbounded-spawn` | 循环中的 `tokio::spawn` | 资源耗尽 | | `regex-in-loop` | 循环内的 `Regex::new()` | 慢 737 倍 | | `clone-in-hot-loop` | 循环内的 `.clone()`(不包括 `Arc`/`Rc` 引用计数克隆) | 慢 48 倍 | | `collect-then-iterate` | `.collect().iter()` | 慢 2.3 倍 | | `vec-no-capacity` | `Vec::new()` + 循环内 push | 慢 1.8 倍 | | `hashmap-no-capacity` | `HashMap::new()` + 循环内 insert | 反复 rehash | | `string-no-capacity` | `String::new()` + 循环内 push_str | 反复 realloc | | `format-in-loop` | 循环内的 `format!()` | 每次迭代均发生内存分配 | | `string-concat-loop` | 循环内的字符串 `+` | 应使用 `push_str()` | | `mutex-in-loop` | 循环内获取锁 | 应在循环外获取一次 | ## 准确性 你无法信任的 linter 会被静默或卸载。cargo-perf 根据人工标注的语料库衡量自身的 **精确率** 和 **召回率**,并在 CI 中强制为这两者设定下限 —— 针对每条规则,而不仅仅是总体数据。全部 14 条规则中的每一条均由 一个正向 fixture(在该触发时必须触发)和一个负向 fixture(在不该触发时必须保持静默)进行评分,因此记分牌不会被 从不运行的规则所欺骗。负向 fixture 直接防范了其他 linter 臭名昭著的误报:`Arc::clone`/`Rc::clone` 引用计数增加、 循环中克隆的 `Copy` 值、循环中的 `io::Read`/`Write` 和 `AtomicUsize::load`、 被误认为是阻塞/数据库调用的自定义 `.output()`/`.load()` 方法, 以及在 `.await` 之前被释放的 async guard。 该语料库通过可重复的 **对抗性 FP/FN 猎杀** 得到了强化 —— 最后一轮 确认了 38 个缺陷并推动了 10 个批次的测试先行修复 —— 现在 下限已渐进式提升至完美的 **1.00 / 1.00**:在此语料库上, 重新引入的误报或丢失的真阳性都会导致构建失败。工具目前确实无法正确处理的情况存放在 `tests/corpus/known_gaps/` (已跟踪,不计入评分)中,而不是默默地拖累数据。 ``` OVERALL TP: 28 FP: 0 FN: 0 precision: 1.00 recall: 1.00 (80 fixtures, 14/14 rules) ``` 使用 `cargo test --test accuracy -- --nocapture` 重现。完整的方法论 —— 记分牌、对抗性猎杀、`known_gaps/` 策略,以及 fuzzing 和真实 crate 的稳健性扫描 —— 请参见 [docs/accuracy.md](docs/accuracy.md)。 ## CI 集成 ### GitHub Action 使用官方的 GitHub Action 进行最简单的设置: ``` # .github/workflows/perf.yml name: Performance Analysis on: [push, pull_request] jobs: cargo-perf: runs-on: ubuntu-latest permissions: contents: read security-events: write # For SARIF upload steps: - uses: actions/checkout@v4 - uses: cschuman/cargo-perf@v1 with: path: '.' fail-on-error: 'true' sarif: 'true' # Enables GitHub Code Scanning integration ``` #### Action 输入 | 输入 | 默认值 | 描述 | |-------|---------|-------------| | `path` | `.` | 要分析的路径 | | `fail-on-error` | `true` | 发现错误则失败 | | `fail-on-warning` | `false` | 发现警告则失败 | | `sarif` | `true` | 将结果上传至 GitHub 代码扫描 | | `version` | `latest` | 要安装的 cargo-perf 版本 | ### 手动设置 ``` # .github/workflows/ci.yml - name: Performance lint run: | cargo install cargo-perf cargo perf --strict --fail-on error ``` 有关用于 GitHub 代码扫描的完整 SARIF 集成工作流,请参见 [examples/github-workflow.yml](examples/github-workflow.yml)。 ## 抑制警告 ``` // cargo-perf-ignore: clone-in-hot-loop let owned = data.clone(); // intentional in cold path ``` 或者针对整个函数: ``` #[allow(cargo_perf::clone_in_hot_loop)] fn cold_path() { ... } ``` ## 基准测试 实际测量结果(Apple M1 Pro,1000 次迭代): | 反面模式 | 影响 | |--------------|--------| | 循环中的 `Regex::new()` | **慢 737 倍** | | 循环中的 `clone()` | **慢 48 倍** | | `collect().iter()` | **慢 2.3 倍** | | async 中的阻塞操作 | 阻塞 runtime 线程 | | 跨越 await 的同步锁 | **死锁** | 有关方法论,请参见 [benchmarks/](benchmarks/)。 ## IDE 集成 cargo-perf 包含一个 LSP 服务器,可在编辑器中提供实时诊断。 ### 安装 ``` cargo install cargo-perf --features lsp ``` ### VS Code 有关扩展信息,请参见 [editors/vscode/](editors/vscode/)。 ### Neovim ``` require('lspconfig.configs').cargo_perf = { default_config = { cmd = { 'cargo-perf', 'lsp' }, filetypes = { 'rust' }, root_dir = require('lspconfig.util').root_pattern('Cargo.toml'), }, } require('lspconfig').cargo_perf.setup({}) ``` ### 其他编辑器 有关 Emacs、Helix、Zed 和通用 LSP 设置,请参见 [editors/README.md](editors/README.md)。 ## 自定义规则(插件系统) 使用你自己的规则扩展 cargo-perf: ``` use cargo_perf::plugin::{PluginRegistry, analyze_with_plugins}; use cargo_perf::rules::{Rule, Diagnostic, Severity}; struct MyCustomRule; impl Rule for MyCustomRule { fn id(&self) -> &'static str { "my-rule" } fn name(&self) -> &'static str { "My Rule" } fn description(&self) -> &'static str { "Detects my anti-pattern" } fn default_severity(&self) -> Severity { Severity::Warning } fn check(&self, ctx: &AnalysisContext) -> Vec { // Your detection logic Vec::new() } } let mut registry = PluginRegistry::new(); registry.add_rule(Box::new(MyCustomRule)); let diagnostics = analyze_with_plugins(path, &config, ®istry)?; ``` 完整示例请参见 [examples/custom_rule.rs](examples/custom_rule.rs)。 ## 许可证 MIT OR Apache-2.0
标签:Rust, SOC Prime, 云安全监控, 可视化界面, 开发工具, 异步编程, 性能优化, 检测绕过, 网络流量审计, 通知系统, 静态分析