AgentSkillsCN

performance-optimization

性能优化技术。在性能、优化、慢速查询或 N+1 查询等问题上,自动应用这些优化策略。

SKILL.md
--- frontmatter
name: performance-optimization
description: "Performans optimizasyonu teknikleri. PERFORMANS, OPTİMİZASYON, YAVAŞLIK veya N+1 QUERY sorunlarında otomatik uygula."
allowed-tools:
  - Read
  - Grep
  - Glob
  - Edit
  - Write
  - Bash

Performance Optimization Standards

Database Optimizasyonu

N+1 Query Problemi

typescript
// ❌ N+1 Query - Her user için ayrı query
const users = await userRepository.findAll()
for (const user of users) {
  user.orders = await orderRepository.findByUserId(user.id) // N query!
}

// ✅ Eager Loading / Join
const users = await userRepository.findAll({
  relations: ['orders'], // Tek query
})

// ✅ Batch Loading
const users = await userRepository.findAll()
const userIds = users.map(u => u.id)
const orders = await orderRepository.findByUserIds(userIds) // 2 query total
const ordersByUser = groupBy(orders, 'userId')
users.forEach(u => u.orders = ordersByUser[u.id] || [])

Index Stratejisi

sql
-- Sık sorgulanan kolonlar
CREATE INDEX idx_users_email ON users(email);

-- Composite index (sorgulama sırasına göre)
CREATE INDEX idx_orders_user_status ON orders(user_id, status);

-- Partial index (filtered queries için)
CREATE INDEX idx_active_users ON users(created_at) WHERE is_active = true;

-- Query explain
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@test.com';

Query Optimization

typescript
// ❌ Gereksiz veri çekme
const users = await db.query('SELECT * FROM users')

// ✅ Sadece gereken kolonlar
const users = await db.query('SELECT id, name, email FROM users')

// ❌ LIKE wildcard başta
WHERE name LIKE '%john%' // Full table scan

// ✅ Prefix match (index kullanır)
WHERE name LIKE 'john%'

// ✅ Full-text search
WHERE to_tsvector(name) @@ to_tsquery('john')

Caching Stratejileri

Cache Levels

code
┌─────────────────┐
│   Client Cache  │  Browser cache, localStorage
├─────────────────┤
│     CDN Cache   │  Static assets, API responses
├─────────────────┤
│  Application    │  Redis, Memcached
│     Cache       │
├─────────────────┤
│  Database Cache │  Query cache, connection pool
└─────────────────┘

Redis Caching Pattern

typescript
// Cache-Aside Pattern
async function getUser(id: string): Promise<User> {
  const cacheKey = `user:${id}`
  
  // 1. Cache'den oku
  const cached = await redis.get(cacheKey)
  if (cached) {
    return JSON.parse(cached)
  }
  
  // 2. DB'den oku
  const user = await userRepository.findById(id)
  if (!user) {
    throw new NotFoundError('User', id)
  }
  
  // 3. Cache'e yaz (TTL: 5 dakika)
  await redis.setex(cacheKey, 300, JSON.stringify(user))
  
  return user
}

// Cache Invalidation
async function updateUser(id: string, data: UpdateUserDto): Promise<User> {
  const user = await userRepository.update(id, data)
  await redis.del(`user:${id}`) // Invalidate
  return user
}

Cache Headers (HTTP)

typescript
// Static assets - Uzun cache
app.use('/static', express.static('public', {
  maxAge: '1y',
  immutable: true,
}))

// API responses - Kısa cache
res.set('Cache-Control', 'private, max-age=60')

// No cache (dynamic data)
res.set('Cache-Control', 'no-store')

Frontend Optimizasyonu

React Performance

tsx
// ✅ Memoization
const ExpensiveComponent = memo(({ data }) => {
  // Heavy render
})

// ✅ useMemo for expensive calculations
const sortedItems = useMemo(() => {
  return items.sort((a, b) => a.name.localeCompare(b.name))
}, [items])

// ✅ useCallback for stable references
const handleClick = useCallback(() => {
  doSomething(id)
}, [id])

// ❌ Inline objects/arrays (her render'da yeni reference)
<Component style={{ color: 'red' }} /> // Her render'da yeni object

// ✅ Stable reference
const styles = useMemo(() => ({ color: 'red' }), [])
<Component style={styles} />

Code Splitting

tsx
// ✅ Lazy loading
const Dashboard = lazy(() => import('./pages/Dashboard'))
const Settings = lazy(() => import('./pages/Settings'))

// Route-based splitting
<Suspense fallback={<Loading />}>
  <Routes>
    <Route path="/dashboard" element={<Dashboard />} />
    <Route path="/settings" element={<Settings />} />
  </Routes>
</Suspense>

Bundle Size

bash
# Bundle analyze
npm run build -- --analyze

# Tree shaking - named imports kullan
import { debounce } from 'lodash-es' // ✅
import _ from 'lodash' // ❌ Tüm lodash

API Optimizasyonu

Pagination

typescript
// Cursor-based (performanslı, büyük veri)
interface PaginatedResponse<T> {
  data: T[]
  cursor: string | null
  hasMore: boolean
}

async function getOrders(cursor?: string, limit = 20) {
  const query = db.query('SELECT * FROM orders')
  
  if (cursor) {
    query.where('id > :cursor', { cursor })
  }
  
  const orders = await query.orderBy('id').limit(limit + 1).getMany()
  const hasMore = orders.length > limit
  
  return {
    data: orders.slice(0, limit),
    cursor: hasMore ? orders[limit - 1].id : null,
    hasMore,
  }
}

Response Compression

typescript
import compression from 'compression'

app.use(compression({
  threshold: 1024, // 1KB üzeri compress
  level: 6,
}))

Performance Checklist

Database

  • N+1 query kontrolü yapıldı
  • Gerekli index'ler oluşturuldu
  • EXPLAIN ANALYZE ile sorgular test edildi
  • Connection pooling aktif

Caching

  • Hot data cache'leniyor
  • Cache invalidation stratejisi var
  • TTL'ler uygun

Frontend

  • Bundle size < 250KB (initial)
  • Code splitting uygulandı
  • Images optimize edildi (WebP, lazy load)
  • Lighthouse score > 90

API

  • Response compression aktif
  • Pagination uygulandı
  • Rate limiting var