Principle 1 Optimize Where It Matters
Premature optimization is root of all evil (Donald Knuth). But ignoring obvious anti-patterns also wrong. Key: measure first optimize second. Tools: Profilers (py-spy Python, pprof Go, YourKit/VisualVM Java, Chrome DevTools Performance tab JS). Logging: Add timing around suspected slow functions. APM: Application Performance Monitoring (SkyWalking, Pinpoint) for production insight.
Rule of thumb: 80% execution time spends in 20% of code. Find that 20% first. Do not optimize easy-to-read-but-rarely-executed helper while leaving O(n^2) loop in hot path untouched.
Principle 2 Algorithm Before Micro-Optimization
Changing O(n^2) to O(n log n) beats any register-level tuning. Real example from 益阳 logistics project: Route optimization for delivery trucks originally brute-force permutation. For 15 stops: 15! = 1.3 trillion combinations - computation took 45 minutes. Replaced with nearest-neighbor heuristic plus 2-opt refinement: Same quality solution (within 5% optimal) computed in 0.3 seconds. That is 9000x speedup from algorithm change not from making code tighter.
Principle 3 IO Usually Bottleneck
In modern applications CPU rarely constraint. Bottlenecks usually: Database queries (network round-trip plus disk I/O plus query execution), External API calls (HTTP latency, rate limiting), File system ops (especially sync I/O), Network bandwidth (large payloads).
Optimization strategies: Database: Add proper indexes (single most impactful DB op), use EXPLAIN analyze plans, consider read replicas for read-heavy workloads, implement caching (Redis/Memcached). API calls: Parallelize independent calls (Promise.all/asyncio.gather/CompletableFuture.allOf), implement caching with TTL, use connection pooling, consider gRPC for internal comms (more efficient than REST/JSON for high-volume). File I/O: Use async I/O (async/await, non-blocking calls), buffer writes, compress large files, consider object storage (OSS/S3) for static assets.
Principle 4 Caching Done Right
Caching most impactful optimization for read-heavy apps. But done wrong creates hard-to-debug bugs.
Cache tiers: L1 In-memory (app-level per-request/singleton, fastest smallest). L2 Distributed cache (Redis/Memcached shared across instances fast medium size). L3 CDN/edge cache (static content geographically distributed large). L4 Database query cache.
Cache invalidation strategies: Time-based TTL (simplest accept slight staleness). Event-driven (update source invalidate cache). Write-through (write to cache and DB atomically). Write-behind (write to cache immediately async persist to DB - riskier but fastest writes).
Common pitfall: Cache stampede (thundering herd) - many requests simultaneously expire regenerate same key. Solution: Mutex lock for regeneration, probabilistic early refresh, or always serve slightly-stale while refreshing background.
Principle 5 Measure Twice Cut Once
Before and after measurements non-negotiable. Record baseline metrics (response time throughput resource utilization). Make optimization change. Measure again. Confirm improvement. If no improvement or regression revert. Git friend - commit before optimization attempts so cleanly revert possible.
A 益阳 team once spent 3 days implementing sophisticated connection pooling optimization. Result: 2% improvement in non-bottleneck area. Meanwhile single missing index on high-traffic table caused 200ms delay per query. Found during profiling AFTER pooling work. Lesson: always profile first optimize measured bottleneck not assumed one.