一键导入
performance
Performance optimization for web applications. Use when optimizing frontend rendering, backend response times, database queries, or system resources.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Performance optimization for web applications. Use when optimizing frontend rendering, backend response times, database queries, or system resources.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
RESTful API design best practices. Use when designing endpoints, request/response schemas, error handling, and API versioning.
Perform thorough code reviews with security, performance, and quality checks. Use when reviewing PRs, auditing code changes, or finding potential bugs.
Database design and optimization. Use for schema design, queries, migrations, indexing, and performance tuning.
Systematic debugging methodology for finding and fixing bugs. Use when investigating issues, tracing errors, or fixing production problems.
Docker and containerization best practices. Use for Dockerfile creation, docker-compose, multi-stage builds, and container optimization.
Technical documentation best practices. Use for writing READMEs, API docs, code comments, and project documentation.
| name | performance |
| description | Performance optimization for web applications. Use when optimizing frontend rendering, backend response times, database queries, or system resources. |
Performance optimization techniques for frontend, backend, and database layers.
| Metric | Target | Description |
|---|---|---|
| LCP | < 2.5s | Largest Contentful Paint |
| FID | < 100ms | First Input Delay |
| CLS | < 0.1 | Cumulative Layout Shift |
// Dynamic imports for code splitting
const Dashboard = lazy(() => import('./pages/Dashboard'));
// Route-based splitting
const routes = [
{
path: '/dashboard',
component: lazy(() => import('./pages/Dashboard')),
},
];
// Next.js Image component
import Image from 'next/image';
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority // Above the fold
placeholder="blur"
/>
// Lazy load below-fold images
<Image
src="/feature.jpg"
loading="lazy"
/>
// Memoize expensive calculations
const sortedData = useMemo(() => {
return data.sort((a, b) => a.name.localeCompare(b.name));
}, [data]);
// Memoize callbacks
const handleClick = useCallback((id: string) => {
setSelected(id);
}, []);
// Memoize components
const ExpensiveList = memo(({ items }) => (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
));
// Virtualize long lists
import { FixedSizeList } from 'react-window';
<FixedSizeList
height={400}
itemCount={10000}
itemSize={35}
>
{({ index, style }) => (
<div style={style}>{items[index].name}</div>
)}
</FixedSizeList>
/* Avoid expensive selectors */
/* ❌ Bad */
div.container ul li a span { }
/* ✅ Good */
.nav-link-text { }
/* Use will-change for animations */
.animated-element {
will-change: transform;
}
/* Contain paint for isolated elements */
.card {
contain: layout paint;
}
// ❌ Bad: Allocates on each iteration
for i := 0; i < 1000; i++ {
result = append(result, processItem(i))
}
// ✅ Good: Pre-allocate slice
result := make([]Item, 0, 1000)
for i := 0; i < 1000; i++ {
result = append(result, processItem(i))
}
var bufferPool = sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
func processRequest(data []byte) {
buf := bufferPool.Get().(*bytes.Buffer)
defer func() {
buf.Reset()
bufferPool.Put(buf)
}()
buf.Write(data)
// Process...
}
// ❌ Bad: Creates new encoder each time
json.NewEncoder(w).Encode(data)
// ✅ Good: Reuse encoder or use sonic for speed
import "github.com/bytedance/sonic"
sonic.Marshal(data)
// Worker pool pattern
func processItems(items []Item, workers int) []Result {
jobs := make(chan Item, len(items))
results := make(chan Result, len(items))
// Start workers
for w := 0; w < workers; w++ {
go func() {
for item := range jobs {
results <- process(item)
}
}()
}
// Send jobs
for _, item := range items {
jobs <- item
}
close(jobs)
// Collect results
output := make([]Result, len(items))
for i := range output {
output[i] = <-results
}
return output
}
┌─────────────┐ miss ┌─────────────┐
│ Client │ ────────── │ Database │
└─────────────┘ └─────────────┘
│ │
│ hit │
▼ │
┌─────────────┐ │
│ Cache │ ◄─────────────────┘
└─────────────┘ populate
import "github.com/redis/go-redis/v9"
type CacheService struct {
client *redis.Client
ttl time.Duration
}
func (c *CacheService) Get(ctx context.Context, key string, dest interface{}) error {
val, err := c.client.Get(ctx, key).Result()
if err == redis.Nil {
return ErrCacheMiss
}
if err != nil {
return err
}
return json.Unmarshal([]byte(val), dest)
}
func (c *CacheService) Set(ctx context.Context, key string, value interface{}) error {
data, err := json.Marshal(value)
if err != nil {
return err
}
return c.client.Set(ctx, key, data, c.ttl).Err()
}
// Cache-aside pattern
func (s *Service) GetUser(ctx context.Context, id string) (*User, error) {
cacheKey := "user:" + id
// Try cache first
var user User
if err := s.cache.Get(ctx, cacheKey, &user); err == nil {
return &user, nil
}
// Cache miss - fetch from DB
user, err := s.db.GetUser(ctx, id)
if err != nil {
return nil, err
}
// Populate cache
s.cache.Set(ctx, cacheKey, user)
return user, nil
}
// Invalidate on update
func (s *Service) UpdateUser(ctx context.Context, user *User) error {
if err := s.db.UpdateUser(ctx, user); err != nil {
return err
}
// Invalidate cache
cacheKey := "user:" + user.ID
s.cache.Delete(ctx, cacheKey)
return nil
}
// Use cache tags for bulk invalidation
func (s *Service) InvalidateUserCaches(ctx context.Context, userID string) {
keys := []string{
"user:" + userID,
"user:profile:" + userID,
"user:settings:" + userID,
}
s.cache.Delete(ctx, keys...)
}
-- Use EXPLAIN ANALYZE
EXPLAIN ANALYZE
SELECT u.*, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.created_at > '2024-01-01'
GROUP BY u.id;
-- Add appropriate indexes
CREATE INDEX idx_users_created_at ON users(created_at);
CREATE INDEX idx_orders_user_id ON orders(user_id);
db, err := sql.Open("postgres", connString)
if err != nil {
return err
}
// Configure pool
db.SetMaxOpenConns(25) // Max connections
db.SetMaxIdleConns(5) // Keep 5 idle
db.SetConnMaxLifetime(5 * time.Minute)
db.SetConnMaxIdleTime(1 * time.Minute)
// ❌ Bad: N+1 queries
users := db.GetAllUsers()
for _, user := range users {
orders := db.GetOrdersByUser(user.ID) // N queries!
}
// ✅ Good: Single query with JOIN or preload
users := db.Preload("Orders").Find(&users)
// Or batch fetch
userIDs := extractIDs(users)
ordersByUser := db.GetOrdersForUsers(userIDs)
import _ "net/http/pprof"
// Enable pprof server
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
// Access profiles:
// http://localhost:6060/debug/pprof/
// http://localhost:6060/debug/pprof/heap
// http://localhost:6060/debug/pprof/goroutine
# CPU profile
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
# Memory profile
go tool pprof http://localhost:6060/debug/pprof/heap
# Visualize
go tool pprof -http=:8080 cpu.prof
func TimingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
wrapped := &responseWriter{ResponseWriter: w}
next.ServeHTTP(wrapped, r)
duration := time.Since(start)
logger.Info("request",
zap.String("method", r.Method),
zap.String("path", r.URL.Path),
zap.Int("status", wrapped.status),
zap.Duration("duration", duration),
)
// Alert slow requests
if duration > 2*time.Second {
logger.Warn("slow request", zap.Duration("duration", duration))
}
})
}