- Rust 97.6%
- Emacs Lisp 0.7%
- Lua 0.7%
- Shell 0.5%
- TypeScript 0.5%
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.52.3 to 1.53.1. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.52.3...tokio-1.53.1) --- updated-dependencies: - dependency-name: tokio dependency-version: 1.53.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|---|---|---|
| .github | ||
| benchmarks | ||
| docs | ||
| editors | ||
| examples | ||
| fuzz | ||
| scripts | ||
| src | ||
| tests | ||
| .gitignore | ||
| .taplo.toml | ||
| action.yml | ||
| cargo-perf.schema.json | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| CONTRIBUTING.md | ||
| DESIGN.md | ||
| LICENSE-APACHE | ||
| LICENSE-MIT | ||
| README.md | ||
| SECURITY.md | ||
cargo-perf
Static analysis for async correctness and runtime performance in Rust.
The Problem
These bugs compile fine and ship to production:
// 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<Data>) {
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 catches all of these.
Installation
Prebuilt binary (fastest — no compile), via cargo-binstall:
cargo binstall cargo-perf
Or build from source:
cargo install cargo-perf
Either way the binary installs as cargo-perf, so it runs as a cargo subcommand: cargo perf.
Adopting on an existing codebase? Don't let pre-existing findings block you — see Getting Started for the baseline-and-ratchet workflow that fails CI only on new issues.
Usage
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
Rules
Errors (High Confidence)
| Rule | What it catches |
|---|---|
async-block-in-async |
std::fs, thread::sleep, blocking I/O in async functions |
lock-across-await |
Synchronous MutexGuard/RwLockGuard (std/parking_lot) held across .await — deadlock risk |
n-plus-one-query |
Database queries inside loops (SQLx, Diesel, SeaORM) |
Note on
lock-across-await: An async lock guard (tokio::sync::Mutex,RwLock) held across.awaitis correct by design — that is what async locks are for. cargo-perf reports that case as a Warning (it serializes tasks and can throttle throughput), not an error. Only synchronous guards held across.awaitare flagged as errors, because those can deadlock the runtime. This is deliberately narrower thanclippy::await_holding_lock, which warns on every guard regardless of lock type.
Warnings (Medium Confidence)
| Rule | What it catches | Impact |
|---|---|---|
unbounded-channel |
mpsc::channel(), unbounded_channel() |
Memory exhaustion |
unbounded-spawn |
tokio::spawn in loops |
Resource exhaustion |
regex-in-loop |
Regex::new() inside loops |
737x slower |
clone-in-hot-loop |
.clone() in loops (excludes Arc/Rc refcount clones) |
48x slower |
collect-then-iterate |
.collect().iter() |
2.3x slower |
vec-no-capacity |
Vec::new() + push in loop |
1.8x slower |
hashmap-no-capacity |
HashMap::new() + insert in loop |
Repeated rehashing |
string-no-capacity |
String::new() + push_str in loop |
Repeated realloc |
format-in-loop |
format!() inside loops |
Allocates each iteration |
string-concat-loop |
String + in loops |
Use push_str() |
mutex-in-loop |
Lock acquired inside loop | Acquire once outside |
Accuracy
A linter you can't trust gets muted or uninstalled. cargo-perf measures its own
precision and recall against a hand-labeled corpus and enforces a floor
on both in CI — per rule, not just in aggregate. Every one of the 14 rules is
scored by both a positive fixture (it must fire when it should) and a negative
fixture (it must stay silent when it shouldn't), so the scorecard can't be
gamed by a rule that never runs. The negatives directly guard the false
positives other linters are infamous for: Arc::clone/Rc::clone refcount
bumps, Copy values cloned in loops, io::Read/Write and AtomicUsize::load
in loops, custom .output()/.load() methods mistaken for blocking/DB calls,
and async guards dropped before .await.
The corpus was hardened by a repeatable adversarial FP/FN hunt — the last
pass confirmed 38 defects and drove a 10-batch, test-first remediation — and the
floor is now ratcheted to a perfect 1.00 / 1.00: on this corpus a
reintroduced false positive or a dropped true positive fails the build. Cases
the tool honestly can't yet get right live in tests/corpus/known_gaps/
(tracked, unscored) rather than dragging the number down quietly.
OVERALL TP: 28 FP: 0 FN: 0 precision: 1.00 recall: 1.00 (80 fixtures, 14/14 rules)
Reproduce with cargo test --test accuracy -- --nocapture. Full methodology —
the scorecard, the adversarial hunt, the known_gaps/ policy, and the fuzzing
and real-crate robustness scans — in docs/accuracy.md.
CI Integration
GitHub Action
Use the official GitHub Action for the easiest setup:
# .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 Inputs
| Input | Default | Description |
|---|---|---|
path |
. |
Path to analyze |
fail-on-error |
true |
Fail if errors found |
fail-on-warning |
false |
Fail if warnings found |
sarif |
true |
Upload results to GitHub Code Scanning |
version |
latest |
cargo-perf version to install |
Manual Setup
# .github/workflows/ci.yml
- name: Performance lint
run: |
cargo install cargo-perf
cargo perf --strict --fail-on error
For a complete workflow with SARIF integration for GitHub Code Scanning, see examples/github-workflow.yml.
Suppressing warnings
// cargo-perf-ignore: clone-in-hot-loop
let owned = data.clone(); // intentional in cold path
Or for a whole function:
#[allow(cargo_perf::clone_in_hot_loop)]
fn cold_path() { ... }
Benchmarks
Real measurements (Apple M1 Pro, 1000 iterations):
| Anti-pattern | Impact |
|---|---|
Regex::new() in loop |
737x slower |
clone() in loop |
48x slower |
collect().iter() |
2.3x slower |
| Blocking in async | Blocks runtime thread |
| Sync lock across await | Deadlock |
See benchmarks/ for methodology.
IDE Integration
cargo-perf includes an LSP server for real-time diagnostics in your editor.
Installation
cargo install cargo-perf --features lsp
VS Code
See editors/vscode/ for the extension.
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({})
Other Editors
See editors/README.md for Emacs, Helix, Zed, and generic LSP setup.
Custom Rules (Plugin System)
Extend cargo-perf with your own rules:
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<Diagnostic> {
// Your detection logic
Vec::new()
}
}
let mut registry = PluginRegistry::new();
registry.add_rule(Box::new(MyCustomRule));
let diagnostics = analyze_with_plugins(path, &config, ®istry)?;
See examples/custom_rule.rs for a complete example.
License
MIT OR Apache-2.0