bookworm-smart-assistant/skills/performance-expert/SKILL.md

6.7 KiB

name: performance-expert description: > 性能优化专家。当用户需要进行前端性能优化、后端性能调优、数据库优化、性能监控、 Core Web Vitals(LCP/FID/CLS)优化、首屏加载优化、内存优化、索引优化, 或说 "性能优化"、"加载慢"、"响应慢" 时使用此技能。 allowed-tools: Read, Glob, Grep, Edit, Write, Bash, mcp__chrome-devtools, mcp__playwright maturity: stable last-reviewed: 2026-02-18 composable: true enhances: [sre-expert, database-tuning-expert, frontend-expert]

性能优化专家 (Performance Expert)

Output Style: 本技能使用内联输出规范

资深性能优化工程师,精通前后端性能分析、优化策略和监控方案。

触发关键词

  • 前端性能: 首屏优化, 加载慢, LCP, FCP, Core Web Vitals
  • 后端性能: 响应慢, API慢, 延迟高, 吞吐量
  • 资源优化: 内存优化, CPU优化, 带宽优化
  • 数据库: 查询慢, 数据库优化, 索引优化
  • 通用: 性能优化, 性能调优, 性能问题

前端性能优化

Core Web Vitals

LCP (Largest Contentful Paint):
  目标: < 2.5s
  优化:
    - 优化关键渲染路径
    - 预加载关键资源
    - 使用 CDN
    - 图片优化

FID (First Input Delay):
  目标: < 100ms
  优化:
    - 减少 JS 执行时间
    - 代码分割
    - Web Worker

CLS (Cumulative Layout Shift):
  目标: < 0.1
  优化:
    - 图片设置尺寸
    - 字体预加载
    - 避免动态插入内容

代码分割

// 路由级别分割
const Dashboard = lazy(() => import('./pages/Dashboard'));

// 组件级别分割
const HeavyChart = lazy(() => import('./components/HeavyChart'));

// 条件加载
const AdminPanel = lazy(() => 
  user.isAdmin ? import('./AdminPanel') : import('./UserPanel')
);

图片优化

// Next.js Image
import Image from 'next/image';

<Image
  src="/hero.jpg"
  width={1200}
  height={600}
  priority  // 关键图片预加载
  placeholder="blur"
  blurDataURL={blurUrl}
/>

// 响应式图片
<picture>
  <source srcSet="image.avif" type="image/avif" />
  <source srcSet="image.webp" type="image/webp" />
  <img src="image.jpg" alt="..." loading="lazy" />
</picture>

缓存策略

// Service Worker 缓存
const CACHE_NAME = 'v1';
const STATIC_ASSETS = ['/app.js', '/styles.css'];

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => cache.addAll(STATIC_ASSETS))
  );
});

// HTTP 缓存头
Cache-Control: public, max-age=31536000, immutable  // 静态资源
Cache-Control: no-cache, must-revalidate           // API 响应

后端性能优化

数据库优化

-- 索引优化
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at DESC);

-- 查询分析
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 1;

-- 避免 N+1
SELECT u.*, o.* FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.id IN (1, 2, 3);

缓存层

// Redis 缓存
async function getUserWithCache(userId: string) {
  const cacheKey = `user:${userId}`;
  
  // 先查缓存
  const cached = await redis.get(cacheKey);
  if (cached) return JSON.parse(cached);
  
  // 查数据库
  const user = await db.user.findUnique({ where: { id: userId } });
  
  // 写入缓存
  await redis.setex(cacheKey, 3600, JSON.stringify(user));
  
  return user;
}

连接池

// 数据库连接池
const pool = new Pool({
  max: 20,           // 最大连接数
  min: 5,            // 最小连接数
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000,
});

性能监控

前端监控

// Web Vitals 监控
import { onLCP, onFID, onCLS } from 'web-vitals';

onLCP((metric) => {
  analytics.send('LCP', metric.value);
});

onFID((metric) => {
  analytics.send('FID', metric.value);
});

onCLS((metric) => {
  analytics.send('CLS', metric.value);
});

后端监控

// 请求耗时中间件
app.use((req, res, next) => {
  const start = Date.now();
  res.on('finish', () => {
    const duration = Date.now() - start;
    metrics.histogram('http_request_duration', duration, {
      method: req.method,
      path: req.path,
      status: res.statusCode,
    });
  });
  next();
});

性能检查清单

### 前端
- [ ] 代码分割和懒加载
- [ ] 图片优化 (WebP/AVIF)
- [ ] 关键 CSS 内联
- [ ] 预加载关键资源
- [ ] 减少第三方脚本

### 后端
- [ ] 数据库索引
- [ ] 查询优化
- [ ] 缓存策略
- [ ] 连接池配置
- [ ] 异步处理

### 网络
- [ ] CDN 配置
- [ ] 压缩 (Gzip/Brotli)
- [ ] HTTP/2
- [ ] 缓存头设置

输出规范

  • 量化性能指标
  • 提供具体优化代码
  • 说明优化效果预期
  • 给出优先级建议

压测脚本生成

k6 负载测试模板

// load-test.js — k6 脚本
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '30s', target: 50 },   // Ramp-up
    { duration: '1m',  target: 50 },   // Steady
    { duration: '30s', target: 200 },  // Spike
    { duration: '1m',  target: 200 },  // Sustained peak
    { duration: '30s', target: 0 },    // Ramp-down
  ],
  thresholds: {
    http_req_duration: ['p(95)<500', 'p(99)<1000'], // 95%<500ms, 99%<1s
    http_req_failed: ['rate<0.01'],                  // 错误率<1%
  },
};

export default function () {
  const res = http.get('http://localhost:3000/api/health');
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 200ms': (r) => r.timings.duration < 200,
  });
  sleep(1);
}
// 运行: k6 run load-test.js
// 云端: k6 cloud run load-test.js

Artillery 压测模板

# artillery-config.yml
config:
  target: "http://localhost:3000"
  phases:
    - duration: 60
      arrivalRate: 10
      name: "Warm up"
    - duration: 120
      arrivalRate: 50
      name: "Sustained load"
  defaults:
    headers:
      Content-Type: "application/json"
scenarios:
  - name: "API health check"
    flow:
      - get:
          url: "/api/health"
          expect:
            - statusCode: 200
# 运行: npx artillery run artillery-config.yml

压测检查清单

  • 基准测试: 单用户响应时间 baseline
  • 阶梯加压: 10→50→100→200 并发
  • 峰值测试: 设计容量 2x 突发
  • 浸泡测试: 正常负载持续 4h+ (检测内存泄漏)
  • 数据库连接池是否耗尽
  • 文件句柄/Socket 是否泄漏
  • GC 暂停是否影响 P99 延迟

禁止事项

  • 不要过早优化
  • 不要忽略监控数据
  • 不要只优化不验证
  • 不要忽视用户体验
  • 不要在没有 baseline 的情况下做优化