# Perf Engineering

> 性能工程技能 - 性能分析、内存优化、启动加速、N+1检测、缓存策略。当你涉及性能优化、内存泄漏、启动速度、N+1慢查询、缓存策略时必须使用此技能。即使用户只是说"这里好慢"或"内存占用太高"，也应触发。

- Skill: `yuexueyu/perf-engineering` (Agent Skill)
- Install (CLI): `npx skillmds@latest add yuexueyu/perf-engineering`
- Raw SKILL.md: https://api.skillmd.com/api/skills/yuexueyu/perf-engineering/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: yuexueyu (https://skillmd.com/u/yuexueyu)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/yuexueyu/perf-engineering

---


# 性能工程技能 (Performance Engineering Skill)

## 快速规则（日常开发时自动加载，只需读到这里）

> **[性能核心清单]** ① 循环内禁止IO/网络/数据库调用（N+1→批量查询） ② 列表>100条必须虚拟化/分页 ③ 启动路径禁止同步网络请求
> **[内存三禁]** ❌循环引用(闭包捕获self/delegate强引用) ❌大图不压缩直接加载 ❌无限缓存无淘汰策略
> **[缓存铁律]** 读多写少=Cache+TTL+主动失效，写多读少=不缓存，❌缓存带认证的个人数据到公共层

写/改涉及性能的代码时，强制遵守：
1. **N+1检测**：循环内有数据库查询/网络请求/文件IO→必须改为批量操作。Grep `for`/`forEach`/`map` 内的查询调用
2. **列表性能**：数据量>100条→虚拟化(LazyVStack/RecyclerView/虚拟滚动)；>1000条→必须分页+游标
3. **图片优化**：必须懒加载+适当分辨率+缓存。大图(>1MB)必须压缩/缩略图。禁止主线程解码大图（解码大图耗时可达数百毫秒，主线程阻塞>16ms就掉帧）
4. **启动优化**：启动路径上禁止同步网络请求/大文件读取/重计算（启动超过3秒用户感知卡死，同步操作直接阻塞主线程）。能延迟的延迟，能异步的异步
5. **内存管理**：闭包捕获检查循环引用(Swift用`[weak self]`)，定时器/观察者必须在deinit中取消
6. **缓存策略**：明确TTL+最大容量+淘汰策略(LRU)。写入时清除相关缓存。❌无限增长的缓存
7. **主线程保护**：IO/网络/重计算禁止在主线程（主线程阻塞>16ms就掉帧，>3s用户感知卡死）。UI更新必须在主线程。检查`DispatchQueue.main`使用正确性
8. **批量操作**：批量写入有数量上限(防OOM)，大数据处理用流式/分批，❌一次加载全部到内存

---

## 完整审查流程（手动 /perf-engineering 或专项审查时执行）

### Phase 1: 性能现状扫描

1. 识别性能关键路径：
   - 应用启动流程（从main到首屏可交互）
   - 核心用户操作（最频繁的3-5个操作）
   - 数据密集操作（列表加载/搜索/导出/同步）
   - 后台任务（定时同步/推送处理/数据清理）

2. 扫描性能风险模式（Grep搜索）：
   - 循环内的IO/网络/数据库调用
   - `DispatchQueue.main.sync`（主线程死锁风险）
   - 大数据量无分页的查询
   - 未使用缓存的重复计算/请求
   - 图片加载无压缩/无缓存

### Phase 2: CPU性能审查

3. 计算密集型操作：
   - 排序/过滤/搜索算法复杂度是否合理（O(n²)→O(n log n)）
   - 正则表达式是否有灾难性回溯风险
   - JSON解析/序列化是否在主线程
   - 加密/哈希操作是否阻塞UI

4. 主线程占用：
   - Grep所有主线程操作，识别耗时操作
   - 文件IO/数据库查询/网络请求是否在后台线程
   - UI更新是否批量处理（而非逐个刷新）
   - 动画帧率是否受后台任务影响

### Phase 3: 内存性能审查

5. 内存泄漏检测模式：
   - **循环引用**：闭包捕获`self`/delegate强引用/Timer持有target
   - **未释放资源**：未关闭的文件句柄/数据库连接/网络会话
   - **观察者泄漏**：NotificationCenter/KVO未移除观察者
   - **缓存无限增长**：内存缓存无最大容量限制/无淘汰策略

6. 内存使用优化：
   - 大数据集是否用分页/流式处理（而非全部加载到内存）
   - 图片是否按显示尺寸缩放（而非加载原图）
   - 临时大对象是否用`autoreleasepool`（ObjC/Swift）
   - 是否有不必要的数据副本（值类型大对象频繁复制）

### Phase 4: IO与网络性能

7. 网络优化：
   - 请求合并：相同数据的多个请求→合并为一个
   - 预取策略：用户即将需要的数据提前加载
   - 压缩：请求/响应是否启用gzip/brotli
   - 连接复用：HTTP/2/Keep-Alive/WebSocket长连接
   - 超时设置：连接超时/读超时/总超时是否合理

8. 磁盘IO优化：
   - 写入合并：高频小写入→批量写入
   - 读取缓存：频繁读取的文件→内存缓存
   - 序列化格式：JSON vs Protobuf vs SQLite（按场景选择）
   - 文件大小：配置文件/缓存文件是否有大小限制

### Phase 5: 数据库性能

9. 查询性能：
   - 慢查询识别：无索引的WHERE/JOIN/ORDER BY
   - N+1查询：循环中逐条查询→批量查询（IN/JOIN）
   - 大偏移分页：`OFFSET 10000`→游标分页(WHERE id > last_id)
   - `SELECT *`→只查需要的字段
   - 子查询→改为JOIN或EXISTS

10. 写入性能：
    - 批量插入：逐条INSERT→批量INSERT/事务包裹
    - 索引维护成本：频繁更新的字段是否有不必要的索引
    - 事务范围：是否最小化（长事务=长时间锁表）

### Phase 6: 渲染与UI性能

11. 列表/滚动性能：
    - 大列表是否使用虚拟化（LazyVStack/UICollectionView/RecyclerView/虚拟滚动）
    - Cell复用是否正确实现
    - 滚动时是否有不必要的布局计算
    - 图片是否异步加载+占位图

12. 渲染优化：
    - 不必要的重绘：状态变化→是否触发全量重绘（应为局部更新）
    - 离屏渲染：圆角+阴影+裁剪组合（iOS上触发离屏渲染）
    - 透明度叠加：多层半透明视图的混合开销
    - 动画性能：是否使用GPU加速的属性（transform/opacity vs layout属性）

### Phase 7: 启动性能

13. 启动耗时分析：
    - 冷启动 vs 热启动
    - 启动阶段拆分：进程创建→dylib加载→main()→首屏渲染→可交互
    - 各阶段耗时估算和优化空间

14. 启动优化清单：
    - 延迟初始化：非首屏需要的模块延迟到使用时初始化
    - 预加载：首屏数据用缓存/本地数据先展示，后台刷新
    - 减少dylib数量（iOS/macOS）：合并小框架
    - 启动任务分级：必须(首屏依赖) > 尽快(用户可能需要) > 延迟(后台即可)

### Phase 8: 缓存策略审查

15. 缓存分层：

| 层级 | 存储 | 速度 | 容量 | 适用场景 |
|------|------|------|------|----------|
| L1 内存缓存 | Dictionary/NSCache | 纳秒 | 小(≤50MB) | 高频读取的小数据 |
| L2 磁盘缓存 | 文件/SQLite | 毫秒 | 中(≤500MB) | 图片/API响应/计算结果 |
| L3 网络缓存 | CDN/HTTP Cache | 秒级 | 大 | 静态资源/公共数据 |

16. 缓存一致性：
    - 写入时主动清除相关缓存（而非只依赖TTL过期）
    - 缓存key设计：包含版本/用户ID/参数hash（防止脏数据）
    - 降级策略：缓存失效时的兜底方案（返回旧数据+提示/loading）

### Phase 9: 输出报告

```
## 性能审查报告

### 性能风险概览
| # | 位置(文件:行号) | 问题类型 | 描述 | 影响 | 优化方案 | 优先级 |

### N+1查询
| # | 文件:行号 | 循环体 | 查询内容 | 优化方案(批量查询) | 预期提升 |

### 内存风险
| # | 文件:行号 | 类型(泄漏/过大/未释放) | 描述 | 修复方案 | 优先级 |

### 启动优化建议
| 阶段 | 当前耗时(估) | 优化方案 | 预期提升 |

### 缓存策略建议
| 数据类型 | 当前策略 | 建议策略 | 预期效果 |

### 渲染性能
| 组件 | 问题 | 优化方案 | 预期效果 |
```

## 性能开发规则（写代码时强制遵守）

### 写代码时强制检查
- ❌ 禁止循环内IO/网络/数据库调用（100条数据=100次查询，批量只需1次，性能差100倍）
- ❌ 禁止主线程同步IO/网络/重计算（主线程阻塞>16ms就掉帧，>3s用户感知卡死）
- ❌ 禁止无限增长的缓存/列表（用户长时间使用后内存持续膨胀直到OOM崩溃）
- ❌ 禁止加载原图到内存（4K照片解码后占~48MB内存，10张=480MB，压缩+缩放后只需几MB）
- ❌ 禁止`SELECT *`+无分页（数据增长后单次返回百万行，耗尽内存和带宽）
- ✅ 大列表必须虚拟化（>100条）
- ✅ 启动路径延迟加载非必需模块
- ✅ 闭包捕获检查循环引用
- ✅ 批量操作有数量上限防OOM

## 性能分析工具速查

### Go
```bash
go test -bench=. -benchmem ./...                    # 基准测试+内存分配
go test -cpuprofile=cpu.prof -memprofile=mem.prof    # 生成profile
go tool pprof -http=:8080 cpu.prof                   # 可视化分析
curl http://localhost:6060/debug/pprof/goroutine?debug=1  # goroutine泄漏
GODEBUG=gctrace=1 ./app                              # GC追踪
```

### 前端（浏览器）
```javascript
// 测量函数执行时间
console.time('render'); doSomething(); console.timeEnd('render');
// Performance API
performance.mark('start'); doWork(); performance.mark('end');
performance.measure('work', 'start', 'end');
// 长任务检测
new PerformanceObserver(list => console.log(list.getEntries()))
  .observe({ entryTypes: ['longtask'] });
```

### 数据库慢查询
```sql
-- MySQL慢查询分析
EXPLAIN ANALYZE SELECT ...;              -- 执行计划+实际耗时
SHOW PROCESSLIST;                        -- 当前连接
SELECT * FROM sys.statements_with_runtimes_in_95th_percentile;  -- P95慢查询
```

## 常见优化模式速查

| 问题 | 症状 | 优化方案 | 预期提升 |
|------|------|----------|----------|
| N+1查询 | 循环内SELECT | JOIN/IN批量查询 | 10-100x |
| 无索引 | 全表扫描 | 添加合适索引 | 10-1000x |
| 大JSON序列化 | 响应慢 | 只返回必要字段/分页 | 2-10x |
| 无缓存热数据 | DB压力大 | Redis/内存缓存+TTL | 5-50x |
| 同步阻塞IO | 主线程卡死 | goroutine/async/Worker | 消除卡顿 |
| 大列表渲染 | 页面卡顿 | 虚拟滚动/分页 | 消除卡顿 |
| 全量导入库 | 首屏慢 | 按需导入/Tree-shaking | 减少30-70%体积 |
| 未压缩图片 | 加载慢 | WebP+lazy load+CDN | 减少50-80%体积 |
| 频繁GC | 吞吐下降 | 对象池/减少分配/sync.Pool | 20-50% |
| 锁竞争 | 并发瓶颈 | 分段锁/无锁结构/channel | 2-10x |

## 约束
- 性能建议必须附带 文件:行号 引用
- 优化方案必须附带预期提升估算（如"减少~200ms"/"内存降低~30%"）
- 不做过早优化——先证明是瓶颈再优化
- 优化不得牺牲代码可读性（除非是关键热路径）
- 缓存策略必须考虑一致性问题，不只追求速度

