关于 perf
面向开发者的性能技能,可对多种语言运行时进行代码分析、基准测试、回归检测并指导优化。它强调以测量结果为依据,并在每次优化后重新运行基准测试。
主要功能
- 01分析 CPU、内存和 I/O
- 02创建并运行基准测试
- 03比较运行结果以检测回归
- 04按测量影响排列性能热点
- 05逐项优化并验证效果
适用场景
- 01查找目标程序的性能热点
- 02建立性能基线
- 03检查更改是否导致性能回归
- 04用基准测试结果验证优化
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ boshu2/ agentops --skill perf安装后在 Claude Code 中输入/perf确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/optimization-proof-loop.mdperf.featureprofiling-playbook.mdsystem-pressure-triage.mdscripts/validate.sh详细介绍
性能分析技能
快速参考:
/perf profile <target>|/perf bench <target>|/perf compare <baseline> <candidate>|/perf optimize <target>
必须执行此工作流。不要只描述它。
适用于任何语言运行时的性能分析、基准测试、回归检测和优化建议。提供可执行的指标,而非含糊的建议。
模式
| 模式 | 命令 | 用途 |
|---|---|---|
| 分析 | /perf profile <target> | 分析执行情况,查找热点 |
| 基准测试 | /perf bench <target> | 创建或运行基准测试 |
| 比较 | /perf compare <baseline> <candidate> | 比较两次运行以检测回归 |
| 优化 | /perf optimize <target> | 分析并应用优化 |
如果未指定模式,则默认使用 分析。
步骤 0:检测语言和工具
根据文件扩展名、go.mod、package.json、pyproject.toml、Cargo.toml 或用户明确输入,识别语言/运行时。选择分析工具链:
如果问题可能源于主机资源压力,而非目标代码性能,请在基准测试前阅读 references/system-pressure-triage.md。
要了解可重复的测量流程、分析器选择和报告指标,请阅读 references/profiling-playbook.md。
| 语言 | 基准测试 | CPU 分析 | 内存分析 | 比较 |
|---|---|---|---|---|
| Go | go test -bench | go tool pprof (cpu) | go tool pprof (alloc) | benchstat |
| Python | pytest-benchmark、timeit | cProfile、py-spy | memory_profiler、tracemalloc | 手动比较 |
| Node | benchmark.js、vitest bench | --prof、clinic.js | --heap-prof、0x | 手动比较 |
| Rust | criterion、cargo bench | cargo flamegraph | heaptrack、DHAT | critcmp |
| Shell | hyperfine | time、strace | 不适用 | hyperfine 内置 |
检查实际安装了哪些工具。如果缺少首选工具,先使用标准库替代方案,再询问用户是否要安装任何工具。
步骤 1:建立基线
先运行现有基准测试。如果没有,则创建基准测试。
1a. 查找现有基准测试
# Go
grep -r "func Benchmark" --include="*_test.go" -l .
# Python
find . -name "test_*" -exec grep -l "benchmark\|@pytest.mark.benchmark" {} +
# Rust
grep -r "#\[bench\]" --include="*.rs" -l .
# Node
find . -name "*.bench.*" -o -name "*.benchmark.*"
1b. 运行或创建基准测试
如果目标已有基准测试,则运行并捕获输出。如果没有,则编写基准测试,覆盖目标函数或模块。
基准测试要求:
- 测量实际运行时间(ops/sec 或 ns/op)
- 测量内存分配(bytes/op、allocs/op)
- 运行足够多次迭代以确保统计稳定性(Go:
-benchtime=3s -count=5) - 在适用时记录延迟百分位数:p50、p95、p99
将原始基线输出保存到 .agents/perf/baseline-YYYY-MM-DD.txt。
1c. Go 基准测试模板
func BenchmarkTargetFunction(b *testing.B) {
// Setup outside the loop
input := prepareInput()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
TargetFunction(input)
}
}
1d. Python 基准测试模板
import pytest
@pytest.mark.benchmark(group="target")
def test_target_benchmark(benchmark):
input_data = prepare_input()
result = benchmark(target_function, input_data)
assert result is not None
步骤 2:分析并识别热点
CPU 分析
找出消耗 CPU 时间最多的函数。
Go:
go test -bench=BenchmarkTarget -cpuprofile=cpu.prof ./...
go tool pprof -top cpu.prof
go tool pprof -text -cum cpu.prof # cumulative view
Python:
python -m cProfile -s cumulative target_script.py
# Or for running processes:
py-spy top --pid <PID>
py-spy record -o profile.svg --pid <PID>
内存分析
找出分配热点和潜在泄漏。
Go:
go test -bench=BenchmarkTarget -memprofile=mem.prof ./...
go tool pprof -top -alloc_space mem.prof
Python:
python -m memory_profiler target_script.py
# Or with tracemalloc in code:
# tracemalloc.start(); ...; snapshot = tracemalloc.take_snapshot()
I/O 分析
识别热路径中的阻塞操作。
- 检查循环中的同步文件 I/O、网络调用或数据库查询。
- 查找缺失的连接池、未缓冲写入,或可并发执行的串行 HTTP 调用。
热点摘要
分析后,按优先级列出:
HOTSPOTS (by cumulative CPU time):
1. pkg/engine.Process 42.3% (1.2s) — main processing loop
2. pkg/engine.parseRecord 28.1% (0.8s) — record deserialization
3. pkg/io.ReadBatch 15.7% (0.45s) — disk reads
步骤 3:分析并提出建议
按预估影响对每项发现进行分类:
| 影响 | 标准 | 操作 |
|---|---|---|
| 高 | 占总耗时的 >20% 或占总分配量的 >50% | 立即修复 |
| 中 | 占总耗时的 5-20% 或存在明显的分配浪费 | 在本次会话中修复 |
| 低 | 占总耗时的 <5%,属于轻微低效 | 记录以便后续处理 |
常见反模式
检查经过性能分析的代码,确认是否存在以下已知的性能杀手:
- 不必要的分配 — 在热点循环中分配内存、在循环中拼接字符串(使用
strings.Builder/[]byte/io.StringWriter) - N+1 查询 — 每个条目都单独调用数据库,而不是批量查询
- 缺少缓存 — 重复计算很少变化的昂贵结果
- 热点路径中的阻塞 I/O — 使用同步网络/磁盘调用,而异步或缓冲 I/O 即可满足需求
- 过度复制 — 按值传递大型结构体、复制切片而不是对其切片
- 数据结构选择不佳 — 可以使用映射查找时却进行线性搜索、切片无界增长且未预先分配容量
- 锁竞争 — 持有互斥锁期间执行 I/O 或长时间计算
- 在循环中编译正则表达式 — 编译一次并复用已编译的模式
- 热点路径中使用反射 — 改用代码生成或类型分支
- 无缓冲通道 — 在 Go 中导致 goroutine 调度开销
对于每项发现,请说明:
- 内容:具体代码位置和模式
- 原因:它如何损害性能(附上性能分析中的数据)
- 修复:具体的代码修改建议
第 4 步:优化(仅限 optimize 模式)
关键规则:一次只进行一项优化。
对于高工作量的优化,在修改代码前加载 references/optimization-proof-loop.md。其中定义了同构重写、基准测试差异以及保留/回退决策的验证约定。
对于每项优化:
- 描述要做的改动
- 应用这一项改动
- 重新运行基准测试套件
- 使用
benchstat(Go)或手动比较结果与基线 - 保留或回退——只保留能带来可测量指标改善的改动
- 使用以下消息格式提交:
perf(<scope>): <description> (+X% throughput)或perf(<scope>): <description> (-X% latency)
验收标准
- 改善必须具有统计显著性(
benchstat的 p < 0.05,或手动比较中一致变化超过 5%) - 不得出现正确性回归——所有现有测试都必须通过
- 不得为了微小收益牺牲可读性(改善不足 2% 不足以证明使用晦涩代码是合理的)
优化顺序
按以下顺序应用优化(预期影响从高到低):
- 算法改进(例如从 O(n^2) 降至 O(n log n))
- 减少分配(预先分配、使用池、复用缓冲区)
- I/O 批处理与缓冲
- 缓存与记忆化
- 并发改进(并行处理相互独立的工作)
- 微优化(仅在性能分析确认其确实重要时进行)
第 5 步:输出报告
将报告写入 .agents/perf/YYYY-MM-DD-perf-<target>.md。
报告模板
# Performance Report: <target>
Date: YYYY-MM-DD
Mode: <profile|bench|compare|optimize>
Language: <detected>
## Summary
<1-2 sentence summary of findings>
## Baseline Metrics
| Metric | Value |
|--------|-------|
| ops/sec | ... |
| ns/op | ... |
| B/op | ... |
| allocs/op | ... |
| p50 latency | ... |
| p95 latency | ... |
| p99 latency | ... |
## Hotspots
<ranked list from Step 2>
## Findings
<classified findings from Step 3>
## Optimizations Applied (if optimize mode)
| Change | Before | After | Improvement |
|--------|--------|-------|-------------|
| ... | ... | ... | +X% |
## After Metrics (if optimize mode)
<same table as baseline, with new values>
## Recommendations
<remaining opportunities not addressed in this session>
Compare 模式详情
运行 /perf compare <baseline> <candidate> 时:
- 查找或重新运行两个版本的基准测试
- 使用对应语言的比较工具:
- Go:
benchstat baseline.txt candidate.txt - Rust:
critcmp baseline candidate - 其他:使用并排表格列出百分比差异
- Go:
- 将回归(慢超过 5% 或分配多出超过 10%)标记为 REGRESSION
- 将改善(快超过 5% 或分配减少超过 10%)标记为 IMPROVEMENT
- 将统计上不显著的变化标记为 NOISE
输出摘要表:
COMPARISON: baseline vs candidate
| Benchmark | Baseline | Candidate | Delta | Verdict |
|-----------|----------|-----------|-------|---------|
| BenchmarkProcess | 1.2ms | 0.9ms | -25% | IMPROVEMENT |
| BenchmarkParse | 450ns | 480ns | +6.7% | REGRESSION |
| BenchmarkIO | 3.1ms | 3.0ms | -3.2% | NOISE |
边界情况
- 没有基准测试且没有明确目标:先运行
/refactor识别热点路径,然后对其进行基准测试。 - 基准测试结果不稳定:增加迭代次数,将任务固定到单个核心(
GOMAXPROCS=1),关闭竞争进程。 - 无法安装性能分析工具:使用
time测量墙钟时间,并通过手动插桩统计分配次数。 - 目标是 CLI 命令:使用
hyperfine对任何语言的命令进行墙钟时间基准测试。
另请参阅
参考文档
-
references/perf.feature — 可执行规范:使用指标分析性能热点、基准测试、比较回归、优化(soc-qk4b)