mcpField
P
performance-tuning

performance-tuning

github.com/noobygains开发11766 次安装3 天前更新
代码仓库

关于 performance-tuning

performance-tuning 是供开发者和编码 Agent 排查软件性能问题的技能。它要求设定可量化目标、分析性能瓶颈、每次只改一项,并比较可重复的测量结果。

主要功能

  1. 01设定量化性能目标
  2. 02建立可重复的基线测量
  3. 03先分析瓶颈再选择改动
  4. 04每次只测量一项改动
  5. 05添加性能回归防护

适用场景

  1. 01排查响应缓慢或超时问题
  2. 02按预算评估内存用量或构建包大小
  3. 03验证拟议优化是否改善实测性能

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/noobygains/godmode --skill performance-tuning

安装后在 Claude Code 中输入/performance-tuning确认已加载。

详细介绍

性能调优

对时间消耗在哪里的直觉,出错的概率往往比正确的概率更高。先测量问题,再通过性能分析找出时间或内存实际消耗的位置,改动一项内容,然后用相同的方法再次测量。没有测量就没有优化:每项改动都必须先用数据证明其合理性,再用数据验证其效果。

首要原则

NO OPTIMISATION WITHOUT A MEASUREMENT PROVING THE PROBLEM

没有例外。没有变通办法。没有捷径。

适用场景

必须使用:

  • 用户、测试或监控报告了运行缓慢、超时、内存占用高、包体积大或成本高。
  • 超出性能预算或目标(延迟百分位数、Core Web Vitals、包体积、查询耗时、冷启动)。
  • 有人要求“优化”“提速”或“提升扩展能力”。
  • 你正准备添加缓存、索引、并发处理、用另一种语言重写,或进行微优化。

跳过:

  • 代码尚未正确运行。正确性优先;调用 godmode:fault-diagnosis 或 godmode:test-first。
  • 没有目标,也没有投诉。“也许哪天会变慢”不算问题;记录下来,然后继续。
  • 初次编写代码时选择合适的算法或数据结构。这属于常规设计,而非调优,前提是不损害清晰度。

操作流程

digraph perf {
    rankdir=TB;
    target [label="1. Target\n(number + percentile)", shape=box];
    baseline [label="2. Baseline\n(repeatable measurement)", shape=box];
    met [label="Target met?", shape=diamond];
    profile [label="3. Profile\n(where does it go?)", shape=box];
    hypo [label="4. One hypothesis", shape=box];
    change [label="5. Change one thing", shape=box];
    remeasure [label="6. Re-measure\n(same method)", shape=box];
    better [label="Significant\nimprovement?", shape=diamond];
    revert [label="Revert", shape=box];
    done [label="7. Record + guard", shape=box];

    target -> baseline -> met;
    met -> done [label="yes"];
    met -> profile [label="no"];
    profile -> hypo -> change -> remeasure -> better;
    better -> met [label="yes, keep"];
    better -> revert [label="no"];
    revert -> hypo;
}
  1. 设定目标。 明确数值、百分位数和场景:“每秒 50 个请求时,GET /orders 的 p95 低于 300 ms”,“移动设备上第 75 百分位的 LCP 不超过 2.5 s”,“压缩后的包体积低于 200 KB”。没有目标就没有结束条件;请向用户询问,或提出一个目标。

  2. 获取可重复的基线。 使用相同的输入数据和环境(接近生产环境,而非调试构建),丢弃预热运行结果,进行多次运行并报告波动范围,而非单个数值。保存准确的命令及其输出。工具见下表。

  3. 先分析,再猜测。 使用性能分析器、查询计划、跟踪记录或包分析器,找出时间、内存或字节消耗的位置。证据应是能指出热点的性能分析产物(火焰图、EXPLAIN ANALYZE 输出、跟踪记录)。常见问题按大致顺序包括:数据库查询(N+1、缺少索引、全表扫描)、串行执行的网络往返、过大的序列化负载、算法复杂度、同步 I/O 和内存 churn。

  4. 提出一个假设,将热点与改动关联起来:“订单列表为每个条目执行一次查询(N+1);改为单条联接查询后,p95 应能从 920 ms 降至 300 ms 以下。”

  5. 只改一项内容。 每次测量只做一项改动,并确保测试通过,以便将效果归因于该改动。将此改动单独提交。

  6. 用完全相同的方法重新测量,并与基线比较,包括波动范围。如果改进处于噪声范围内或未达到预期,就撤销改动,即使它“理应”有所帮助。如果改动有效,就从第 2 步开始,以新的基线继续,直到达到目标。

  7. 记录并设置防护。 在 PR 描述中写明改动前后的数值、测量方法和提交。添加防护,避免回归悄然发生:在 CI 中运行基准测试、进行预算检查(godmode:quality-gates),或编写断言查询次数的测试。

测量工具

内容测量方式分析方式
端到端测量命令或脚本hyperfine --warmup 3 'cmd'(比较两项:hyperfine 'old' 'new')下方对应语言的分析器
Pythonpytest-benchmark、timeitpy-spy record -o profile.svg -- python app.py、py-spy top --pid <pid>
Node.jshyperfine、基准测试库node --cpu-prof app.js(CPU)、node --heap-prof app.js(内存);在浏览器 DevTools 中打开生成的文件
Gogo test -bench . -benchmemgo test -bench . -cpuprofile cpu.out,然后运行 go tool pprof cpu.out
RustCriterion 等基准测试框架在 Linux 上使用 perf 或火焰图工具
PostgreSQL 查询EXPLAIN (ANALYZE, BUFFERS) <query>查看同一执行计划:关注顺序扫描、行数估算错误和循环
负载下的 HTTP 服务使用固定请求速率的负载生成器,并报告百分位数APM 跟踪或服务器上的语言分析器
网页lighthouse <url>(实验室数据);使用真实用户的现场数据评估 Core Web Vitals浏览器 DevTools 的 Performance 面板
包体积打包工具的分析器或大小限制检查同一分析器,按模块查看

EXPLAIN ANALYZE 会执行语句。对于 INSERT、UPDATE 或 DELETE,请在事务中运行并回滚。

预算

预算可以将“足够快”变成一项检查。应在用户能感受到结果的地方设置预算,并在 CI 中强制执行。

类型预算示例数值来源
最大内容绘制2.5 s 或更短Core Web Vitals“良好”标准;页面加载的第 75 百分位数,分别统计移动端和桌面端
下一次绘制交互200 ms 或更短Core Web Vitals“良好”标准;第 75 百分位数
累积布局偏移0.1 或更低Core Web Vitals“良好”标准;第 75 百分位数
API 延迟预期负载下各端点的 p95 和 p99产品要求或服务级别目标
查询耗时生产规模数据下的每条查询耗时端点预算减去其他所有开销
包或二进制文件大小按入口点统计,使用 gzip 压缩目标设备和网络所能承受的大小
内存每个进程的峰值常驻内存容器或设备的限制,并留出余量

应报告百分位数,而不是平均值:平均值会掩盖用户抱怨的慢请求。

反模式

反模式失败原因应采取的做法
先加缓存会带来数据过时、失效错误和内存开销,还会掩盖慢代码修复慢查询或慢调用;只有在测量确认有需要且制定了失效方案时才使用缓存
什么都建索引索引会拖慢写入并占用存储空间添加查询计划所要求的索引,并用新的查询计划确认效果
什么都异步或并行处理对 CPU 密集型工作没有收益,还会增加调试难度并引入竞争条件仅在分析结果显示独立 I/O 正在等待时使用并发
微调分析器未标记的循环只节省纳秒,却牺牲代码清晰度只修改热点路径上的代码
一次做多项更改无法判断哪些更改有效,哪些有害每次测量只做一项更改
对调试版或极小数据进行基准测试测得的数值无法应用于生产环境使用接近生产环境的构建、数据量和硬件
只运行一次,不看波动范围噪声会被误认为性能提升预热后运行多次,并比较波动范围
用更快的语言重写为一个通常只需优化一条查询的热点带来数月风险先进行分析,再优先修复热点

认知陷阱

自我辩解事实
“我知道瓶颈在哪里。”性能分析器之所以存在,就是因为这种判断经常出错。拿出性能分析结果。
“规模扩大后这里会变慢。”那就在该规模下用负载测试进行测量。在此之前,这只是猜测。
“缓存会让一切都变快。”缓存只会让缓存命中更快,并让其他所有事情变得更复杂。先测量到底哪里慢。
“最佳实践建议在这里添加索引。”最佳实践不了解你的查询。查询计划才了解。
“既然我在处理这里,不如也顺便调优一下。”未测量、未规划的改动会给下一次测量带来干扰。一次只做一项改动。
“感觉快了。”感觉不是测量结果。运行相同的基准测试。
“改进幅度很小,但也不会有坏处。”每项改动都会牺牲清晰度并占用审查时间。落在测量噪声范围内的改动应予以回退。

护栏

绝不:

  • 在没有目标、基线和性能分析结果的情况下进行优化。
  • 在两次测量之间更改不止一项内容。
  • 保留效果落在测量噪声范围内的改动。
  • 为未经测量的收益牺牲正确性、安全性或可读性。
  • 仅用平均值或单次运行结果作为证据。

始终:

  • 保存精确的测量命令及其运行前后的输出。
  • 在接近生产环境的构建和环境中进行测量。
  • 在每一步优化过程中确保测试全部通过。
  • 为每项保留的优化成果添加回归防护(基准测试、预算或查询数量测试)。

关联

  • godmode:fault-diagnosis:当缓慢实际上是一个故障(卡死、泄漏、重试风暴)时,在那里进行诊断。
  • godmode:system-design:当性能分析结果指向架构(数据模型、服务边界、托管方式)时,将决策转到那里。
  • godmode:quality-gates:将预算和基准测试设为 CI 门禁。
  • godmode:test-first:在优化改动代码之前,用测试固定行为。
  • godmode:grounding:根据最新文档核验性能分析器的提示和框架的性能功能。
  • godmode:completion-gate:优化前后的数据就是工作已完成的证据。

评论

支持 Markdown