optimize

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Performance Optimization Skill

性能优化技能

Systematic approach to identifying and fixing performance issues.
识别和修复性能问题的系统化方法。

Name

名称

han-core:optimize - Optimize code for performance, readability, or efficiency
han-core:optimize - 针对性能、可读性或效率优化代码

Synopsis

概要

/optimize [arguments]
/optimize [arguments]

Core Principle

核心原则

Measure, don't guess. Optimization without data is guesswork.
先测量,再优化。 没有数据支撑的优化只是猜测。

The Cardinal Rule

首要规则

NEVER optimize without measuring first
Why: Premature optimization wastes time on non-issues while missing real problems.
Exception: Obvious O(n^2) algorithms when O(n) alternatives exist.
绝对不要在未测量的情况下进行优化
原因: 过早优化会在无关问题上浪费时间,却忽略真正的性能瓶颈。
例外情况: 当存在O(n)替代方案时,明显的O(n²)算法可以直接优化。

Optimization Process

优化流程

1. Measure Current State (Baseline)

1. 测量当前状态(基准线)

Before touching any code, establish metrics:
Frontend Performance:
bash
undefined
在修改任何代码之前,先建立衡量指标:
前端性能:
bash
undefined

Chrome DevTools Performance tab

Chrome DevTools 性能面板

Lighthouse audit

Lighthouse 审计

npm run build && du -sh dist/ # Bundle size

**Backend Performance:**

```bash
npm run build && du -sh dist/ # 打包体积

**后端性能:**

```bash

Add timing logs

添加计时日志

start = Time.now result = expensive_operation() elapsed = Time.now - start Logger.info("Operation took #{elapsed}ms")

**Database:**

```bash
start = Time.now result = expensive_operation() elapsed = Time.now - start Logger.info("Operation took #{elapsed}ms")

**数据库:**

```bash

PostgreSQL

PostgreSQL

EXPLAIN ANALYZE SELECT ...;
EXPLAIN ANALYZE SELECT ...;

Check query time in logs

在日志中查看查询时间

grep "SELECT" logs/production.log | grep "Duration:"

**Metrics to capture:**

- Load time / response time
- Time to interactive
- Bundle size
- Memory usage
- Query duration
- Render time
grep "SELECT" logs/production.log | grep "Duration:"

**需要捕获的指标:**

- 加载时间/响应时间
- 可交互时间
- 打包体积
- 内存占用
- 查询耗时
- 渲染时间

2. Profile to Find Bottlenecks

2. 分析定位性能瓶颈

Don't guess where the problem is - profile:
Browser Profiling:
  • Chrome DevTools > Performance tab
  • Record interaction
  • Look for long tasks (> 50ms)
  • Check for layout thrashing
Server Profiling:
bash
undefined
不要猜测问题所在——用分析工具:
浏览器分析:
  • Chrome DevTools > 性能面板
  • 记录交互过程
  • 查找长任务(>50ms)
  • 检查布局抖动
服务端分析:
bash
undefined

Add detailed timing

添加详细计时

defmodule Profiler do def measure(label, func) do start = System.monotonic_time(:millisecond) result = func.() elapsed = System.monotonic_time(:millisecond) - start Logger.info("#{label}: #{elapsed}ms") result end end
defmodule Profiler do def measure(label, func) do start = System.monotonic_time(:millisecond) result = func.() elapsed = System.monotonic_time(:millisecond) - start Logger.info("#{label}: #{elapsed}ms") result end end

Use it

使用示例

Profiler.measure("Database query", fn -> Repo.all(User) end)

**React Profiling:**

```bash
Profiler.measure("Database query", fn -> Repo.all(User) end)

**React 分析:**

```bash

React DevTools Profiler

React DevTools 分析器

Look for:

关注:

- Unnecessary re-renders

- 不必要的重渲染

- Slow components (> 16ms for 60fps)

- 缓慢的组件(60fps下耗时>16ms)

- Large component trees

- 庞大的组件树

undefined
undefined

3. Identify Root Cause

3. 定位根本原因

Common performance issues:
Frontend:
  • Large bundle size (lazy load, code split)
  • Unnecessary re-renders (memoization)
  • Blocking JavaScript (defer, async)
  • Unoptimized images (WebP, lazy loading)
  • Too many network requests (bundle, cache)
  • Memory leaks (cleanup useEffect)
Backend:
  • N+1 queries (preload associations)
  • Missing database indexes
  • Expensive computations in loops
  • Synchronous external API calls
  • Large JSON responses
  • Inefficient algorithms
Database:
  • Missing indexes
  • Inefficient query structure
  • Too many joins
  • Fetching unnecessary columns
  • No query result caching
常见性能问题:
前端:
  • 打包体积过大(懒加载、代码分割)
  • 不必要的重渲染(记忆化)
  • 阻塞式JavaScript(defer、async)
  • 未优化的图片(WebP、懒加载)
  • 过多网络请求(打包、缓存)
  • 内存泄漏(清理useEffect)
后端:
  • N+1查询(预加载关联数据)
  • 缺失数据库索引
  • 循环中的昂贵计算
  • 同步外部API调用
  • 过大的JSON响应
  • 低效算法
数据库:
  • 缺失索引
  • 低效的查询结构
  • 过多关联查询
  • 获取不必要的列
  • 未缓存查询结果

4. Apply Targeted Optimization

4. 实施针对性优化

One change at a time - Measure impact of each change
每次只做一处修改——衡量每处修改的影响

Frontend Optimizations

前端优化

Bundle Size Reduction:
typescript
// Before: Import entire library
import _ from 'lodash'

// After: Import only what's needed
import debounce from 'lodash/debounce'

// Or: Use native alternatives
const unique = [...new Set(array)]  // Instead of _.uniq(array)
React Performance:
typescript
// Before: Re-renders on every parent render
function ChildComponent({ items }) {
  return <div>{items.map(...)}</div>
}

// After: Only re-render when items change
const ChildComponent = React.memo(function ChildComponent({ items }) {
  return <div>{items.map(...)}</div>
}, (prev, next) => prev.items === next.items)

// Before: Recreates function every render
function Parent() {
  const handleClick = () => { ... }
  return <Child onClick={handleClick} />
}

// After: Stable function reference
function Parent() {
  const handleClick = useCallback(() => { ... }, [])
  return <Child onClick={handleClick} />
}
Code Splitting:
typescript
// Before: All in main bundle
import HeavyComponent from './HeavyComponent'

// After: Lazy load when needed
const HeavyComponent = React.lazy(() => import('./HeavyComponent'))

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <HeavyComponent />
    </Suspense>
  )
}
Image Optimization:
typescript
// Before: Full-size image
<img src="/hero.jpg" />

// After: Responsive, lazy-loaded
<img
  src="/hero-800w.webp"
  srcSet="/hero-400w.webp 400w, /hero-800w.webp 800w"
  loading="lazy"
  alt="Hero image"
/>
减小打包体积:
typescript
// 优化前:导入整个库
import _ from 'lodash'

// 优化后:仅导入所需部分
import debounce from 'lodash/debounce'

// 或者:使用原生替代方案
const unique = [...new Set(array)]  // 替代 _.uniq(array)
React 性能优化:
typescript
// 优化前:父组件渲染时子组件也会重渲染
function ChildComponent({ items }) {
  return <div>{items.map(...)}</div>
}

// 优化后:仅在items变化时重渲染
const ChildComponent = React.memo(function ChildComponent({ items }) {
  return <div>{items.map(...)}</div>
}, (prev, next) => prev.items === next.items)

// 优化前:每次渲染都会重新创建函数
function Parent() {
  const handleClick = () => { ... }
  return <Child onClick={handleClick} />
}

// 优化后:稳定的函数引用
function Parent() {
  const handleClick = useCallback(() => { ... }, [])
  return <Child onClick={handleClick} />
}
代码分割:
typescript
// 优化前:全部打包进主文件
import HeavyComponent from './HeavyComponent'

// 优化后:需要时懒加载
const HeavyComponent = React.lazy(() => import('./HeavyComponent'))

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <HeavyComponent />
    </Suspense>
  )
}
图片优化:
typescript
// 优化前:全尺寸图片
<img src="/hero.jpg" />

// 优化后:响应式、懒加载
<img
  src="/hero-800w.webp"
  srcSet="/hero-400w.webp 400w, /hero-800w.webp 800w"
  loading="lazy"
  alt="Hero image"
/>

Backend Optimizations

后端优化

N+1 Query Fix:
elixir
undefined
修复N+1查询:
elixir
// 优化前:N+1查询(1次用户查询 + N次帖子查询)
users = Repo.all(User)
Enum.map(users, fn user ->
  posts = Repo.all(from p in Post, where: p.user_id == ^user.id)
  {user, posts}
end)

// 优化后:总共2次查询
users = Repo.all(User) |> Repo.preload(:posts)
Enum.map(users, fn user -> {user, user.posts} end)
数据库索引:
sql
-- 优化前:缓慢查询
SELECT * FROM users WHERE email = 'user@example.com';
-- 顺序扫描(5000ms)

-- 优化后:添加索引
CREATE INDEX idx_users_email ON users(email);
-- 索引扫描(2ms)
缓存:
elixir
// 优化前:每次请求都执行昂贵计算
def get_popular_posts do
  # 复杂聚合查询(500ms)
  Repo.all(from p in Post, ...)
end

// 优化后:缓存5分钟
def get_popular_posts do
  Cachex.fetch(:app_cache, "popular_posts", fn ->
    result = Repo.all(from p in Post, ...)
    {:commit, result, ttl: :timer.minutes(5)}
  end)
end
批量处理:
elixir
// 优化前:逐个处理
Enum.each(user_ids, fn id ->
  user = Repo.get(User, id)
  send_email(user)
end)

// 优化后:批量获取
users = Repo.all(from u in User, where: u.id in ^user_ids)
Enum.each(users, &send_email/1)

Before: N+1 queries (1 for users + N for posts)

算法优化

users = Repo.all(User) Enum.map(users, fn user -> posts = Repo.all(from p in Post, where: p.user_id == ^user.id) {user, posts} end)
降低复杂度:
typescript
// 优化前:O(n²) - 嵌套循环
function findDuplicates(arr: number[]): number[] {
  const duplicates = []
  for (let i = 0; i < arr.length; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] === arr[j] && !duplicates.includes(arr[i])) {
        duplicates.push(arr[i])
      }
    }
  }
  return duplicates
}

// 优化后:O(n) - 单次遍历+Set
function findDuplicates(arr: number[]): number[] {
  const seen = new Set<number>()
  const duplicates = new Set<number>()

  for (const num of arr) {
    if (seen.has(num)) {
      duplicates.add(num)
    }
    seen.add(num)
  }

  return Array.from(duplicates)
}

After: 2 queries total

5. 衡量优化效果(成果验证)

users = Repo.all(User) |> Repo.preload(:posts) Enum.map(users, fn user -> {user, user.posts} end)

**Database Indexing:**

```sql
-- Before: Slow query
SELECT * FROM users WHERE email = 'user@example.com';
-- Seq Scan (5000ms)

-- After: Add index
CREATE INDEX idx_users_email ON users(email);
-- Index Scan (2ms)
Caching:
elixir
undefined
优化后必须重新测量:
markdown
undefined

Before: Expensive calculation every request

优化内容:[修改的具体内容]

优化前

def get_popular_posts do

Complex aggregation query (500ms)

Repo.all(from p in Post, ...) end
  • 加载时间:3.2s
  • 打包体积:850KB
  • 可交互时间:4.1s

After: Cache for 5 minutes

修改点

def get_popular_posts do Cachex.fetch(:app_cache, "popular_posts", fn -> result = Repo.all(from p in Post, ...) {:commit, result, ttl: :timer.minutes(5)} end) end

**Batch Processing:**

```elixir
  • 懒加载HeavyComponent
  • 切换为lodash-es以支持摇树优化
  • 为ProductList添加React.memo

Before: Process one at a time

优化后

Enum.each(user_ids, fn id -> user = Repo.get(User, id) send_email(user) end)
  • 加载时间:1.8s(减少44%)
  • 打包体积:520KB(减少39%)
  • 可交互时间:2.3s(减少44%)

After: Batch fetch

验证证据

users = Repo.all(from u in User, where: u.id in ^user_ids) Enum.each(users, &send_email/1)
undefined

```bash

Algorithm Optimization

优化前

Reduce Complexity:
typescript
// Before: O(n^2) - nested loops
function findDuplicates(arr: number[]): number[] {
  const duplicates = []
  for (let i = 0; i < arr.length; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] === arr[j] && !duplicates.includes(arr[i])) {
        duplicates.push(arr[i])
      }
    }
  }
  return duplicates
}

// After: O(n) - single pass with Set
function findDuplicates(arr: number[]): number[] {
  const seen = new Set<number>()
  const duplicates = new Set<number>()

  for (const num of arr) {
    if (seen.has(num)) {
      duplicates.add(num)
    }
    seen.add(num)
  }

  return Array.from(duplicates)
}
$ npm run build dist/main.js 850.2 KB

5. Measure Impact (Proof of Work)

优化后

ALWAYS measure after optimization:
markdown
undefined
$ npm run build dist/main.js 520.8 KB

**使用成果验证技能记录证据**

Optimization: [What was changed]

6. 验证正确性

Before

  • Load time: 3.2s
  • Bundle size: 850KB
  • Time to interactive: 4.1s
测试必须仍然通过:
bash
undefined

Changes

运行完整测试套件

  • Lazy loaded HeavyComponent
  • Switched to lodash-es for tree shaking
  • Added React.memo to ProductList
npm test # 前端 mix test # 后端

After

手动验证

- 功能正常运行

- 边界情况已处理

- 未引入新bug

  • Load time: 1.8s (-44%)
  • Bundle size: 520KB (-39%)
  • Time to interactive: 2.3s (-44%)
undefined

Evidence

优化类型


```bash
性能优化:
  • 算法复杂度降低
  • 数据库查询优化
  • 缓存策略
  • 懒加载与代码分割
代码质量优化:
  • 简化与清晰化
  • 消除重复代码
  • 更优的命名与结构
  • 模式改进
资源效率优化:
  • 内存占用减少
  • 打包体积优化
  • 网络请求减少
  • 资源优化

Before

常见优化目标

前端检查清单

$ npm run build dist/main.js 850.2 KB
  • 打包体积 < 200KB(gzip压缩后)
  • 首次内容绘制 < 1.5s
  • 可交互时间 < 3s
  • 无布局偏移(CLS < 0.1)
  • 图片已优化(WebP、懒加载)
  • 按路由分割代码
  • 移除未使用代码(摇树优化)
  • CSS关键路径优化

After

后端检查清单

$ npm run build dist/main.js 520.8 KB

**Use proof-of-work skill to document evidence**
  • API响应时间 < 200ms(p95分位)
  • 数据库查询已优化(使用EXPLAIN ANALYZE)
  • 无N+1查询
  • 存在合适的索引
  • 昂贵操作已缓存
  • 缓慢任务使用后台作业
  • 连接池已配置
  • 大数据集使用分页

6. Verify Correctness

数据库检查清单

Tests must still pass:
bash
undefined
  • 频繁查询的列已建立索引
  • 已审查查询执行计划
  • 无全表扫描
  • 合理使用LIMIT
  • 关联查询已优化(从小表开始)
  • 统计信息已更新(ANALYZE)

Run full test suite

优化模式

懒加载模式

npm test # Frontend mix test # Backend
typescript
// 基于路由的代码分割
const routes = [
  {
    path: '/admin',
    component: lazy(() => import('./pages/Admin'))
  },
  {
    path: '/dashboard',
    component: lazy(() => import('./pages/Dashboard'))
  }
]

Manual verification

记忆化模式

- Feature still works

- Edge cases handled

- No new bugs introduced

undefined
typescript
// 昂贵计算
const ExpensiveComponent = ({ data }) => {
  // 仅在data变化时重新计算
  const processedData = useMemo(() => {
    return data.map(item => expensiveTransform(item))
  }, [data])

  return <div>{processedData.map(...)}</div>
}

Optimization Types

数据库查询优化模式

Performance:
  • Algorithm complexity reduction
  • Database query optimization
  • Caching strategies
  • Lazy loading and code splitting
Code Quality:
  • Simplification and clarity
  • Removing duplication
  • Better naming and structure
  • Pattern improvements
Resource Efficiency:
  • Memory usage reduction
  • Bundle size optimization
  • Network request reduction
  • Asset optimization
elixir
// 替代多次查询
users = Repo.all(User)
posts = Repo.all(Post)
comments = Repo.all(Comment)

// 使用关联查询和预加载
users =
  User
  |> join(:left, [u], p in assoc(u, :posts))
  |> join(:left, [u, p], c in assoc(p, :comments))
  |> preload([u, p, c], [posts: {p, comments: c}])
  |> Repo.all()

Common Optimization Targets

反模式

Frontend Checklist

优化错误的内容

  • Bundle size < 200KB (gzipped)
  • First Contentful Paint < 1.5s
  • Time to Interactive < 3s
  • No layout shift (CLS < 0.1)
  • Images optimized (WebP, lazy loading)
  • Code split by route
  • Unused code removed (tree shaking)
  • CSS critical path optimized
错误:花费数小时优化仅运行一次的函数
正确:优化每页加载运行10000次的函数
始终先分析以找到真正的瓶颈

Backend Checklist

过早优化

  • API response time < 200ms (p95)
  • Database queries optimized (EXPLAIN ANALYZE)
  • No N+1 queries
  • Appropriate indexes exist
  • Expensive operations cached
  • Background jobs for slow tasks
  • Connection pooling configured
  • Pagination for large datasets
错误:“这可能会很慢,我先优化一下”
正确:“这确实很慢(测量耗时500ms),我需要优化”

Database Checklist

微优化

  • Indexes on frequently queried columns
  • Query execution plan reviewed
  • No full table scans
  • Appropriate use of LIMIT
  • Joins optimized (smallest table first)
  • Statistics up to date (ANALYZE)
错误:用for循环替换.map()以节省1ms
正确:减少200KB打包体积以节省1000ms
专注于高影响的优化

Optimization Patterns

为了性能牺牲功能

Lazy Loading Pattern

typescript
// Route-based code splitting
const routes = [
  {
    path: '/admin',
    component: lazy(() => import('./pages/Admin'))
  },
  {
    path: '/dashboard',
    component: lazy(() => import('./pages/Dashboard'))
  }
]
错误:移除功能以提升速度
正确:保留功能,优化实现方式
性能优化不应以正确性为代价

Memoization Pattern

无证据的优化

typescript
// Expensive calculation
const ExpensiveComponent = ({ data }) => {
  // Only recalculate when data changes
  const processedData = useMemo(() => {
    return data.map(item => expensiveTransform(item))
  }, [data])

  return <div>{processedData.map(...)}</div>
}
错误:“我觉得这样会更快” [修改代码]
正确:“分析工具显示这部分耗时占比80%” [测量、优化、再次测量]

Database Query Optimization Pattern

需要考虑的权衡

elixir
undefined
性能 vs 可读性:
typescript
// 可读性更强
const result = items
  .filter(item => item.active)
  .map(item => item.name)

// 速度更快(一次遍历而非两次)
const result = []
for (const item of items) {
  if (item.active) {
    result.push(item.name)
  }
}
问题: 性能提升是否值得牺牲可读性?先分析测量。
性能 vs 可维护性:
  • 缓存会增加复杂度
  • 记忆化会增加内存开销
  • 代码分割会增加打包管理成本
始终记录所做的权衡

Instead of multiple queries

工具与命令

users = Repo.all(User) posts = Repo.all(Post) comments = Repo.all(Comment)
前端:
bash
undefined

Use join and preload

打包分析

users = User |> join(:left, [u], p in assoc(u, :posts)) |> join(:left, [u, p], c in assoc(p, :comments)) |> preload([u, p, c], [posts: {p, comments: c}]) |> Repo.all()
undefined
npm run build -- --analyze

Anti-Patterns

Lighthouse 审计

Optimizing the Wrong Thing

BAD: Spending hours optimizing function that runs once
GOOD: Optimize the function that runs 10,000 times per page load
Always profile first to find real bottlenecks
npx lighthouse https://example.com --view

Premature Optimization

体积分析

BAD: "This might be slow, let me optimize it"
GOOD: "This IS slow (measured 500ms), let me optimize it"
npx webpack-bundle-analyzer dist/stats.json

**后端:**

```bash

Micro-optimizations

数据库查询分析

BAD: Replacing `.map()` with `for` loop to save 1ms
GOOD: Reducing bundle size by 200KB to save 1000ms
Focus on high-impact optimizations
EXPLAIN ANALYZE SELECT ...;

Breaking Functionality for Performance

分析Elixir代码

BAD: Remove feature to make it faster
GOOD: Keep feature, make implementation faster
Performance should not come at cost of correctness
:eprof.start() :eprof.profile(fn -> YourModule.function() end) :eprof.stop()
undefined

Optimizing Without Evidence

输出格式

BAD: "I think this will be faster" [changes code]
GOOD: "Profiler shows this takes 80% of time" [measures, optimizes, measures again]
  1. 当前状态:基准指标或问题
  2. 分析:问题原因
  3. 建议修改:具体优化方案
  4. 预期影响:预测的改进效果
  5. 验证:优化成果的证据(使用成果验证技能)

Trade-offs to Consider

示例场景

Performance vs Readability:
typescript
// More readable
const result = items
  .filter(item => item.active)
  .map(item => item.name)

// Faster (one loop instead of two)
const result = []
for (const item of items) {
  if (item.active) {
    result.push(item.name)
  }
}
Question: Is the perf gain worth the readability loss? Profile first.
Performance vs Maintainability:
  • Caching adds complexity
  • Memoization adds memory overhead
  • Code splitting adds bundle management
Always document the trade-off made
当用户说:
  • “这个函数太慢了”
  • “优化这个模块中的数据库查询”
  • “减小这个组件的打包体积”
  • “让这段代码更易读”
  • “这个页面加载时间太长”

Tools & Commands

与其他技能的集成

Frontend:
bash
undefined
  • 使用成果验证技能记录测量数据
  • 优化时遵循童子军规则技能(让代码比优化前更优秀)
  • 使用简洁性原则技能(更简洁的代码通常更快)
  • 使用代码审查技能验证优化质量

Bundle analysis

谨记

npm run build -- --analyze
  1. 先测量——找到真正的瓶颈
  2. 每次只改一处——明确哪项修改起了作用
  3. 衡量影响——验证优化效果
  4. 保留正确性——测试必须通过
  5. 记录权衡——解释原因
错误的快速代码毫无用处。正确且足够快的代码才是完美的。

Lighthouse audit

npx lighthouse https://example.com --view

Size analysis

npx webpack-bundle-analyzer dist/stats.json

**Backend:**

```bash

Database query analysis

EXPLAIN ANALYZE SELECT ...;

Profile Elixir code

:eprof.start() :eprof.profile(fn -> YourModule.function() end) :eprof.stop()
undefined

Output Format

  1. Current state: Baseline metrics or issues
  2. Analysis: What's causing the problem
  3. Proposed changes: Specific optimizations
  4. Expected impact: Predicted improvements
  5. Verification: Proof of improvement (use proof-of-work skill)

Examples

When the user says:
  • "This function is too slow"
  • "Optimize the database queries in this module"
  • "Reduce the bundle size for this component"
  • "Make this code more readable"
  • "This page takes too long to load"

Integration with Other Skills

  • Use proof-of-work skill to document measurements
  • Use boy-scout-rule skill while optimizing (leave better than found)
  • Use simplicity-principles skill (simpler is often faster)
  • Use code-review skill to verify optimization quality

Remember

  1. Measure first - Find real bottlenecks
  2. One change at a time - Know what helped
  3. Measure impact - Verify improvement
  4. Preserve correctness - Tests must pass
  5. Document trade-offs - Explain why
Fast code that's wrong is useless. Correct code that's fast enough is perfect.