RTK Performance Analysis
RTK 性能分析
Hard Targets (Non-Negotiable)
硬性指标(不可妥协)
| Metric | Target | Blocker |
|---|
| Startup time | <10ms | Release blocker |
| Binary size (stripped) | <5MB | Release blocker |
| Memory (resident) | <5MB | Release blocker |
| Token savings per filter | ≥60% | Release blocker |
| 指标 | 目标 | 发布阻塞条件 |
|---|
| 启动时间 | <10ms | 阻塞发布 |
| 二进制文件大小(裁剪后) | <5MB | 阻塞发布 |
| 驻留内存 | <5MB | 阻塞发布 |
| 单次过滤Token节省率 | ≥60% | 阻塞发布 |
Benchmark Startup Time
启动时间基准测试
Install hyperfine (once)
安装 hyperfine(仅需一次)
Baseline (before changes)
基准值(变更前)
hyperfine 'rtk git status' --warmup 3 --export-json /tmp/before.json
hyperfine 'rtk git status' --warmup 3 --export-json /tmp/before.json
After changes — rebuild first
变更后 —— 先重新构建
Compare against installed
和已安装版本对比
hyperfine 'target/release/rtk git status' 'rtk git status' --warmup 3
hyperfine 'target/release/rtk git status' 'rtk git status' --warmup 3
Target: <10ms mean time
目标:平均耗时 <10ms
Check Binary Size
检查二进制文件大小
Release build with strip=true (already in Cargo.toml)
开启 strip=true 的Release构建(已在Cargo.toml中配置)
cargo build --release
ls -lh target/release/rtk
cargo build --release
ls -lh target/release/rtk
If too large — check what's contributing
如果体积过大 —— 检查占用来源
cargo bloat --release --crates
cargo bloat --release -n 20
cargo bloat --release --crates
cargo bloat --release -n 20
Install: cargo install cargo-bloat
安装方式:cargo install cargo-bloat
/usr/bin/time -l target/release/rtk git status 2>&1 | grep "maximum resident"
/usr/bin/time -l target/release/rtk git status 2>&1 | grep "maximum resident"
Target: <5,000,000 bytes (5MB)
目标:<5,000,000 字节 (5MB)
/usr/bin/time -v target/release/rtk git status 2>&1 | grep "Maximum resident"
/usr/bin/time -v target/release/rtk git status 2>&1 | grep "Maximum resident"
Target: <5,000 kbytes
目标:<5,000 千字节
Regex Compilation Audit
正则编译审计
Regex compilation on every function call is a common perf killer:
Find all Regex::new calls
查找所有 Regex::new 调用
grep -n "Regex::new" src/*.rs
grep -n "Regex::new" src/*.rs
Verify ALL are inside lazy_static! blocks
确认所有调用都在 lazy_static! 块内
Any Regex::new outside lazy_static! = performance bug
任何位于 lazy_static! 外的 Regex::new 都属于性能Bug
```rust
// ❌ Recompiles on every filter_line() call
fn filter_line(line: &str) -> bool {
let re = Regex::new(r"^error").unwrap(); // BAD
re.is_match(line)
}
// ✅ Compiled once at first use
lazy_static! {
static ref ERROR_RE: Regex = Regex::new(r"^error").unwrap();
}
fn filter_line(line: &str) -> bool {
ERROR_RE.is_match(line) // GOOD
}
```rust
// ❌ 每次调用filter_line()都会重新编译
fn filter_line(line: &str) -> bool {
let re = Regex::new(r"^error").unwrap(); // 错误写法
re.is_match(line)
}
// ✅ 首次使用时仅编译一次
lazy_static! {
static ref ERROR_RE: Regex = Regex::new(r"^error").unwrap();
}
fn filter_line(line: &str) -> bool {
ERROR_RE.is_match(line) // 正确写法
}
Dependency Impact Assessment
依赖影响评估
Before adding any new crate:
Check startup impact (measure before adding)
检查对启动速度的影响(添加依赖前先测量)
hyperfine 'rtk git status' --warmup 3
hyperfine 'rtk git status' --warmup 3
Add dependency to Cargo.toml
在Cargo.toml中添加依赖
hyperfine 'target/release/rtk git status' --warmup 3
hyperfine 'target/release/rtk git status' --warmup 3
If startup increased >1ms — investigate
如果启动耗时增加>1ms —— 排查原因
If startup increased >3ms — reject the dependency
如果启动耗时增加>3ms —— 拒绝引入该依赖
Forbidden dependencies
禁用的依赖
| Crate | Reason | Alternative |
|---|
| +5-10ms startup | Blocking |
| +5-10ms startup | Blocking I/O |
| Thread pool init overhead | Sequential iteration |
| Pulls tokio | (blocking) if HTTP needed |
| Crate | 原因 | 替代方案 |
|---|
| 增加5-10ms启动耗时 | 阻塞式 |
| 增加5-10ms启动耗时 | 阻塞式I/O |
| 线程池初始化开销 | 顺序迭代 |
| 会引入tokio依赖 | 如需HTTP功能使用(阻塞式) |
Dependency weight check
依赖权重检查
After cargo build --release
执行cargo build --release之后
cargo build --release --timings
cargo build --release --timings
Open target/cargo-timings/cargo-timing.html
打开 target/cargo-timings/cargo-timing.html
Look for crates with long compile times (correlates with complexity)
查找编译时间长的crate(和复杂度正相关)
Allocation Profiling
内存分配分析
macOS — use Instruments
macOS —— 使用Instruments
instruments -t Allocations target/release/rtk git log -10
instruments -t Allocations target/release/rtk git log -10
Or use cargo-instruments
或者使用cargo-instruments
cargo install cargo-instruments
cargo instruments --release -t Allocations -- git log -10
Common RTK allocation hotspots:
```rust
// ❌ Allocates new String on every line
let lines: Vec<String> = input.lines().map(|l| l.to_string()).collect();
// ✅ Borrow slices
let lines: Vec<&str> = input.lines().collect();
// ❌ Clone large output unnecessarily
let raw_copy = output.stdout.clone();
// ✅ Use reference until you actually need to own
let display = &output.stdout;
cargo install cargo-instruments
cargo instruments --release -t Allocations -- git log -10
RTK常见内存分配热点:
```rust
// ❌ 每一行都分配新的String
let lines: Vec<String> = input.lines().map(|l| l.to_string()).collect();
// ✅ 借用切片
let lines: Vec<&str> = input.lines().collect();
// ❌ 不必要地克隆大型输出
let raw_copy = output.stdout.clone();
// ✅ 在真正需要所有权之前使用引用
let display = &output.stdout;
Token Savings Measurement
Token节省率测算
rust
// In tests — always verify claims
fn count_tokens(text: &str) -> usize {
text.split_whitespace().count()
}
#[test]
fn test_savings_claim() {
let input = include_str!("../tests/fixtures/mycmd_raw.txt");
let output = filter_output(input).unwrap();
let input_tokens = count_tokens(input);
let output_tokens = count_tokens(&output);
let savings = 100.0 * (1.0 - output_tokens as f64 / input_tokens as f64);
assert!(
savings >= 60.0,
"Expected ≥60% savings, got {:.1}% ({} → {} tokens)",
savings, input_tokens, output_tokens
);
}
rust
// 在测试中始终验证指标达标情况
fn count_tokens(text: &str) -> usize {
text.split_whitespace().count()
}
#[test]
fn test_savings_claim() {
let input = include_str!("../tests/fixtures/mycmd_raw.txt");
let output = filter_output(input).unwrap();
let input_tokens = count_tokens(input);
let output_tokens = count_tokens(&output);
let savings = 100.0 * (1.0 - output_tokens as f64 / input_tokens as f64);
assert!(
savings >= 60.0,
"预期节省≥60%,实际为{:.1}% ({} → {} 个Token)",
savings, input_tokens, output_tokens
);
}
Before/After Regression Check
变更前后回归检查
Template for any performance-sensitive change:
cargo build --release
hyperfine 'target/release/rtk git status' --warmup 5 --export-json /tmp/before.json
/usr/bin/time -l target/release/rtk git status 2>&1 | grep "maximum resident"
ls -lh target/release/rtk
cargo build --release
hyperfine 'target/release/rtk git status' --warmup 5 --export-json /tmp/before.json
/usr/bin/time -l target/release/rtk git status 2>&1 | grep "maximum resident"
ls -lh target/release/rtk
... edit code ...
... 编辑代码 ...
3. Rebuild and compare
3. 重新构建并对比
cargo build --release
hyperfine 'target/release/rtk git status' --warmup 5 --export-json /tmp/after.json
/usr/bin/time -l target/release/rtk git status 2>&1 | grep "maximum resident"
ls -lh target/release/rtk
cargo build --release
hyperfine 'target/release/rtk git status' --warmup 5 --export-json /tmp/after.json
/usr/bin/time -l target/release/rtk git status 2>&1 | grep "maximum resident"
ls -lh target/release/rtk
Startup: jq '.results[0].mean' /tmp/before.json /tmp/after.json
启动时间对比:jq '.results[0].mean' /tmp/before.json /tmp/after.json
If after > before + 1ms: investigate
如果变更后数值 > 变更前+1ms:排查问题
If after > 10ms: regression, do not merge
如果变更后数值 > 10ms:存在性能回归,禁止合并