SuperAPI AI Directory

verify-quality-performance

Deployment & operations

View repository

Updated 10-16 10:20

About this skill

Performance — performance optimization

Entry/Exit

  • Entry: Performance below target (LCP > 2.5s, slow page response), pre-launch performance review
  • Exit: Quantifiable performance improvement + regression tests
  • Points to: After optimization, return to verify-workflow-review or ship-workflow-ship
  • Preload: CANON.md
  • Output path: Performance improvement report → verify-workflow-review review

When not to use

  • No quantifiable performance target, baseline, or user-perceivable slow point
  • Just routine code cleanup or readability optimization
  • The problem is first and foremost a functional bug, security risk, or unclear architectural boundary

Iron Law

Process: MEASURE → IDENTIFY → FIX → VERIFY → GUARD

MEASURE    → 收集指标(Lighthouse、RUM、profiler)
IDENTIFY   → 定位瓶颈(找出最大的一个瓶颈)
FIX        → 一次改一个(只修测量证明有问题的)
VERIFY     → 重新测量(对比 before/after)
GUARD      → 加回归测试或性能预算

Core Web Vitals targets

Metric Good Needs Work Poor
LCP (Largest Contentful Paint) ≤ 2.5s 2.5-4.0s > 4.0s
INP (Interaction to Next Paint) ≤ 200ms 200-500ms > 500ms
CLS (Cumulative Layout Shift) ≤ 0.1 0.1-0.25 > 0.25

TTFB (Time to First Byte): ≤ 800ms is good.

Bottleneck identification

前端瓶颈:
├── 大 JS Bundle (> 200KB gzipped) → 代码拆分/lazy loading
├── 大图片 (> 500KB) → 压缩/WebP/响应式尺寸
├── 布局偏移 → 显式 width/height
├── 长任务 (> 50ms) → 拆分或 Web Worker
└── 未缓存 → 设置 Cache-Control header

后端瓶颈:
├── 慢查询 → EXPLAIN ANALYZE + 加索引
├── N+1 Queries → JOIN/batch 加载
├── 无分页 → 游标或偏移分页
├── 缺失缓存 → Redis/内存缓存热点数据
└── 同步阻塞 → 异步/队列

Common fixes

N+1 Queries

// Bad: N+1 —— 每个 task 产生一个额外查询
const tasks = await db.tasks.findMany();
for (const t of tasks) {
  t.assignee = await db.users.findById(t.assigneeId);  // +1 query per task
}

// Good: 一次 JOIN 加载
const tasks = await db.tasks.findMany({ include: { assignee: true } });

Unbounded queries

// Bad: 返回全部数据
app.get('/tasks', async (req, res) => {
  const tasks = await db.tasks.findMany();
  res.json(tasks);
});

// Good: 分页 + 限制
app.get('/tasks', async (req, res) => {
  const { page = 1, pageSize = 20 } = req.query;
  const tasks = await db.tasks.findMany({
    skip: (page - 1) * pageSize,
    take: Math.min(pageSize, 100),  // 硬上限
  });
  res.json({ data: tasks, pagination: { page, pageSize } });
});

Image optimization

<!-- 响应式 + 现代格式 + 懒加载 -->
<img
  srcset="hero-640.webp 640w, hero-1280.webp 1280w"
  sizes="(max-width: 768px) 100vw, 50vw"
  src="hero-1280.webp"
  alt="产品图片"
  width="1280"
  height="720"
  loading="lazy"
/>

Missing caching

Cache-Control 策略:
├── 静态资源 (JS/CSS/Fonts) → max-age=31536000, immutable
├── 图片 → max-age=86400
├── API 响应 (变化慢) → max-age=60, stale-while-revalidate=300
└── API 响应 (实时) → no-store

Performance budget

{
  "budgets": [
    { "resourceType": "script", "budget": 200 },   // KB gzipped
    { "resourceType": "style", "budget": 50 },
    { "metric": "LCP", "budget": 2500 },            // ms
    { "metric": "CLS", "budget": 0.1 }
  ]
}

Verification evidence

The output or record must include:

  • Input/Source: The spec, plan, code, feedback, or release context that was read.
  • Actions taken: The checks, generation, fixes, exports, or release steps actually completed.
  • Verification results: Commands, review conclusions, artifact paths, screenshots, or manual confirmation.
  • Blocker/rollback: Failed items, rollback paths, or issues that need a human partner decision.

Common claims

Claim Reality Consequence
"It's fast on my machine" Your MacBook Pro ≠ the user's 4G Android. Measure with Lighthouse (simulated 4G + mid-tier CPU). Fast locally ≠ fast for users → after launch, LCP > 4s on 4G devices → user bounce rate increases 30-50%.
"Just add more caching" Caching masks the problem. Fix the query/loading first, then cache. Caching masks slow queries → slow queries are instantly exposed when the cache expires → user experience drops off a cliff during peak periods.
"I added React.memo + useMemo everywhere" Over-memoizing is as harmful as under-memoizing. Every memo has comparison cost. Measure clearly where it is needed. Over-memoizing → comparison cost > render cost → total time instead increases by 5-15%; unmeasured memo optimization direction is random.
"Ship first, optimize performance later" Performance problems after launch = users have already left. Set a budget from day one. Launching without a budget → users' first experience is slow → 7-day retention drops 20-30%, and "optimize later" on average = never.
"Optimize all bottlenecks" Optimize the biggest bottleneck. Unless measurement proves the rest are worth it—don't fix them. Optimize everything → change scope too large → regression risk uncontrollable → one optimization introducing a bug will invalidate all optimizations.

Red Flags — STOP

  • Starting "optimization" without measurement
  • Bundling multiple performance fixes together (don't know which one works)
  • Not re-measuring after optimization (don't know what you changed)
  • Premature optimization ("in case it's needed fast later" — is it needed now?)
  • N+1 queries appearing in a loop
  • List endpoint has no pagination

Verification Checklist

  • Before and After measurement data exists
  • Performance improvement quantified (LCP from Xms → Yms)
  • No new performance regressions introduced
  • Added performance regression tests or CI budget checks
  • Only modified the parts that measurements proved problematic
  • N+1 query detection passes
  • List endpoint has pagination limits

Verification Failure Handling

Failure Scenario Handling
Starting optimization without measurement data STOP. Go back to the MEASURE step and collect Lighthouse/RUM/profiler data. No baseline = guessing.
No performance improvement after optimization Revert the fix and re-identify the bottleneck. You may have found the wrong bottleneck—go back to IDENTIFY.
Optimization introduces a functional regression Revert the optimization, fix the regression first, then re-measure. Performance optimization must not sacrifice functional correctness.
Unable to reproduce the performance issue Simulate production conditions: 4G network + mid-tier CPU + real data volume. Local test conditions are not the same as production.
Multiple bottlenecks exist at the same time Fix only the largest one. After fixing, re-measure before looking at the next one. Do not batch optimize—you cannot tell which one works.

Good and Bad Examples

Good — quantified before/after + bottleneck evidence

Lighthouse measures LCP 4.2s → IDENTIFY pinpoints N+1 queries as the bottleneck → FIX changes one thing at a time → VERIFY re-measures LCP 1.8s (57% improvement) → GUARD adds a performance budget. Every step has measurement data, not guesses.

Bad — "feels faster" with no measurement

"I added caching, the page should be faster" — no before/after data, no bottleneck identification, no re-measurement. You may have optimized an unimportant bottleneck, or introduced a new regression without discovering it.

Output Template

After performance optimization is complete, the output must include:

## Performance Optimization Report

### Baseline
- LCP: [X]ms → [Y]ms (改善 [Z]%)
- INP: [X]ms → [Y]ms
- CLS: [X] → [Y]

### Bottleneck Identified
- 位置: [文件:行号]
- 类型: N+1 / 无界查询 / 大 bundle / 未缓存 / 长任务
- 测量证据: [profiler/screenshot 数据]

### Fix Applied
- 改动: [描述]
- 文件: [路径]
- 变更行数: [N] 行

### Verification
- Before/after 测量对比: [数据]
- 无功能回归: ✅ / ❌
- 性能预算检查: ✅ / ❌