optimize
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePerformance 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
undefinedChrome DevTools Performance tab
Chrome DevTools 性能面板
Lighthouse audit
Lighthouse 审计
npm run build && du -sh dist/ # Bundle size
**Backend Performance:**
```bashnpm run build && du -sh dist/ # 打包体积
**后端性能:**
```bashAdd timing logs
添加计时日志
start = Time.now
result = expensive_operation()
elapsed = Time.now - start
Logger.info("Operation took #{elapsed}ms")
**Database:**
```bashstart = Time.now
result = expensive_operation()
elapsed = Time.now - start
Logger.info("Operation took #{elapsed}ms")
**数据库:**
```bashPostgreSQL
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 timegrep "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
undefinedAdd 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:**
```bashProfiler.measure("Database query", fn ->
Repo.all(User)
end)
**React 分析:**
```bashReact DevTools Profiler
React DevTools 分析器
Look for:
关注:
- Unnecessary re-renders
- 不必要的重渲染
- Slow components (> 16ms for 60fps)
- 缓慢的组件(60fps下耗时>16ms)
- Large component trees
- 庞大的组件树
undefinedundefined3. 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
undefinedBefore: 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
```bashAlgorithm 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
undefinedChanges
运行完整测试套件
- 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%)
undefinedEvidence
优化类型
```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
—
undefinedtypescript
// 昂贵计算
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
undefinedUse 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()
undefinednpm 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 loadAlways 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
**后端:**
```bashMicro-optimizations
数据库查询分析
BAD: Replacing `.map()` with `for` loop to save 1ms
GOOD: Reducing bundle size by 200KB to save 1000msFocus on high-impact optimizations
EXPLAIN ANALYZE SELECT ...;
Breaking Functionality for Performance
分析Elixir代码
BAD: Remove feature to make it faster
GOOD: Keep feature, make implementation fasterPerformance should not come at cost of correctness
:eprof.start()
:eprof.profile(fn -> YourModule.function() end)
:eprof.stop()
undefinedOptimizing Without Evidence
输出格式
BAD: "I think this will be faster" [changes code]
GOOD: "Profiler shows this takes 80% of time" [measures, optimizes, measures again]- 当前状态:基准指标或问题
- 分析:问题原因
- 建议修改:具体优化方案
- 预期影响:预测的改进效果
- 验证:优化成果的证据(使用成果验证技能)
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
- 先测量——找到真正的瓶颈
- 每次只改一处——明确哪项修改起了作用
- 衡量影响——验证优化效果
- 保留正确性——测试必须通过
- 记录权衡——解释原因
错误的快速代码毫无用处。正确且足够快的代码才是完美的。
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
—
- Current state: Baseline metrics or issues
- Analysis: What's causing the problem
- Proposed changes: Specific optimizations
- Expected impact: Predicted improvements
- 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
—
- Measure first - Find real bottlenecks
- One change at a time - Know what helped
- Measure impact - Verify improvement
- Preserve correctness - Tests must pass
- Document trade-offs - Explain why
Fast code that's wrong is useless. Correct code that's fast enough is perfect.
—