$npx -y skills add krzysztofsurdy/code-virtuoso --skill performanceApplication performance optimization patterns and profiling-driven methodology. Use when the user asks to optimize application speed, reduce latency, diagnose slow queries, fix N+1 problems, implement caching layers, profile memory usage, tune database queries, apply lazy loading
| 1 | # Performance Optimization |
| 2 | |
| 3 | Performance work follows one rule above all others: measure before you change anything. Intuition about bottlenecks is wrong more often than it is right. Every optimization should start with profiling, produce a hypothesis, apply a targeted fix, and verify with another measurement. |
| 4 | |
| 5 | ## Core Principles |
| 6 | |
| 7 | | Principle | Meaning | |
| 8 | |---|---| |
| 9 | | **Measure first** | Never optimize without profiling data - gut feelings about bottlenecks are unreliable | |
| 10 | | **Optimize the critical path** | Focus on the code that runs most frequently or blocks user-visible latency | |
| 11 | | **Set budgets** | Define acceptable latency, throughput, and resource usage before you start | |
| 12 | | **Avoid premature optimization** | Readable, correct code first - optimize only when measurements show a real problem | |
| 13 | | **Know your tradeoffs** | Every optimization trades something (memory for speed, complexity for throughput, freshness for latency) | |
| 14 | |
| 15 | --- |
| 16 | |
| 17 | ## Profiling and Benchmarking |
| 18 | |
| 19 | Profiling identifies where time and resources are spent. Without it, you are guessing. |
| 20 | |
| 21 | ### Types of Profiling |
| 22 | |
| 23 | | Type | What It Reveals | When to Use | |
| 24 | |---|---|---| |
| 25 | | **CPU profiling** | Hot functions, call frequency, execution time distribution | Slow request handling, high CPU usage | |
| 26 | | **Memory profiling** | Allocation rates, heap size, object retention, leaks | Growing memory usage, OOM errors, GC pressure | |
| 27 | | **I/O profiling** | Disk reads/writes, network calls, blocking waits | Slow file operations, external service latency | |
| 28 | | **Database profiling** | Query execution time, query count per request, slow queries | High DB load, N+1 patterns, missing indexes | |
| 29 | |
| 30 | ### The Profiling Workflow |
| 31 | |
| 32 | 1. **Baseline** - Capture metrics under normal conditions before any changes |
| 33 | 2. **Identify** - Find the hotspot consuming the most time or resources |
| 34 | 3. **Hypothesize** - Form a specific theory about why it is slow |
| 35 | 4. **Fix** - Apply a single, targeted change |
| 36 | 5. **Verify** - Measure again to confirm improvement and check for regressions |
| 37 | |
| 38 | ### Performance Budgets |
| 39 | |
| 40 | Define limits that trigger action when exceeded: |
| 41 | |
| 42 | - **Response time**: P50, P95, P99 latency targets per endpoint |
| 43 | - **Throughput**: Minimum requests per second under expected load |
| 44 | - **Resource usage**: CPU, memory, and connection limits per service |
| 45 | - **Page weight**: Maximum transfer size for frontend assets |
| 46 | |
| 47 | See [Profiling Patterns Reference](references/profiling-patterns.md) for detailed profiling workflows, bottleneck signatures, and load testing strategies. |
| 48 | |
| 49 | --- |
| 50 | |
| 51 | ## Caching Strategies |
| 52 | |
| 53 | Caching eliminates redundant computation and data fetching by storing results closer to where they are needed. |
| 54 | |
| 55 | ### Cache Layers |
| 56 | |
| 57 | | Layer | Location | Latency | Use Case | |
| 58 | |---|---|---|---| |
| 59 | | **L1 - In-process** | Application memory (object cache, memoization) | Nanoseconds | Hot data accessed many times per request | |
| 60 | | **L2 - Distributed** | Redis, Memcached, shared cache | Sub-millisecond to low milliseconds | Data shared across application instances | |
| 61 | | **HTTP cache** | Browser, reverse proxy (Varnish, Nginx) | Zero network round-trip for client cache | Static assets, cacheable API responses | |
| 62 | | **CDN** | Edge servers worldwide | Low latency from geographic proximity | Static files, pre-rendered pages, media | |
| 63 | | **Database cache** | Query result cache, buffer pool | Varies | Repeated identical queries | |
| 64 | |
| 65 | ### Invalidation Approaches |
| 66 | |
| 67 | | Strategy | How It Works | Best For | |
| 68 | |---|---|---| |
| 69 | | **TTL-based** | Cache entries expire after a fixed duration | Data that tolerates bounded staleness | |
| 70 | | **Event-based** | Cache is cleared when the source data changes | Data that must stay fresh after writes | |
| 71 | | **Write-through** | Writes update both the cache and the backing store simultaneously | Read-heavy workloads needing strong consistency | |
| 72 | | **Write-behind** | Writes update the cache immediately; backing store is updated asynchronously | High write throughput where eventual consistency is acceptable | |
| 73 | |
| 74 | ### Cache Stampede Prevention |
| 75 | |
| 76 | When a popular cache key expires, many concurrent requests may all try to regenerate it at once, overwhelming the backend. Three approaches prevent this: |
| 77 | |
| 78 | - **Locking** - Only one request regenerates; others wait or serve stale data |
| 79 | - **Probabilistic early recomputation** - Requests randomly refresh the cache before expiration, spreading regeneration over time |
| 80 | - **Request coalescing** - Duplicate in-flight requests are collapsed |