P

Performance Profiler & Optimizer

Identifies performance bottlenecks in web applications and provides specific optimization recommendations with measurable impact.

SkillClipticsperformancev1.0.0MIT
0 views0 copies

Performance Profiler & Optimizer

Systematically identify performance bottlenecks across your full stack — from frontend rendering to database queries — and apply targeted optimizations with measurable impact.

When to Use This Template

Choose Performance Profiler & Optimizer when:

  • Your application has noticeable latency, slow page loads, or degrading response times
  • You need to profile CPU, memory, or I/O hotspots in Node.js, Python, or browser code
  • Database queries are slow and you need index recommendations and query plan analysis
  • You want to measure Core Web Vitals and optimize frontend rendering performance

Consider alternatives when:

  • You need infrastructure scaling decisions (use load testing tools like k6 or Artillery)
  • Your performance issue is purely network-related (use network diagnostic tools)
  • You need APM dashboards and alerting (use Datadog, New Relic, or Grafana)

Quick Start

# .claude/skills/performance-profiler-optimizer.yml name: performance-profiler-optimizer description: Profile and optimize application performance prompt: | Analyze the specified code for performance issues. Profiling approach: 1. Identify hot paths and bottlenecks 2. Measure current baseline metrics 3. Recommend specific optimizations with expected impact 4. Implement changes with before/after benchmarks Focus areas: CPU usage, memory allocation, I/O operations, database queries, rendering performance, bundle size.

Example invocation:

claude "Profile the /api/dashboard endpoint — it takes 3 seconds to respond"

Sample analysis output:

Performance Analysis: GET /api/dashboard
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total response time: 3,142ms

Breakdown:
  Database queries:     2,450ms (78%) ← BOTTLENECK
    - getUserStats:     1,200ms (N+1 query detected)
    - getRecentOrders:    850ms (missing index on created_at)
    - getNotifications:   400ms (full table scan)
  Business logic:         380ms (12%)
    - aggregateMetrics:   290ms (unoptimized loop)
  Serialization:          180ms (6%)
  Middleware:             132ms (4%)

Recommendations:
  1. Add index on orders(user_id, created_at) → saves ~700ms
  2. Batch getUserStats into single query → saves ~900ms
  3. Add WHERE clause to notifications → saves ~350ms
  Expected improvement: 3,142ms → ~1,100ms (65% faster)

Core Concepts

Profiling Strategy Matrix

LayerToolMetricsThreshold
FrontendLighthouse, Web VitalsLCP, FID, CLS, TTFBLCP < 2.5s, CLS < 0.1
APICustom timing middlewareResponse time, throughputp95 < 500ms
DatabaseEXPLAIN ANALYZE, slow query logQuery time, rows scanned< 100ms per query
MemoryHeap snapshots, --inspectHeap growth, GC frequencyNo upward trend
CPUNode --prof, perf_hooksEvent loop delay, CPU %Loop delay < 10ms

Node.js Performance Instrumentation

// Middleware for automatic endpoint profiling function performanceMiddleware(req, res, next) { const start = process.hrtime.bigint(); const metrics = { queries: [], memory: process.memoryUsage() }; // Patch database client to track query timing const originalQuery = req.db.query; req.db.query = async function(sql, params) { const qStart = process.hrtime.bigint(); const result = await originalQuery.call(this, sql, params); const qDuration = Number(process.hrtime.bigint() - qStart) / 1e6; metrics.queries.push({ sql: sql.substring(0, 200), duration: qDuration }); return result; }; res.on('finish', () => { const totalMs = Number(process.hrtime.bigint() - start) / 1e6; const queryMs = metrics.queries.reduce((sum, q) => sum + q.duration, 0); if (totalMs > 1000) { console.warn(`SLOW: ${req.method} ${req.path} ${totalMs.toFixed(0)}ms`, { total: totalMs, database: queryMs, application: totalMs - queryMs, queryCount: metrics.queries.length, slowestQuery: metrics.queries.sort((a, b) => b.duration - a.duration)[0] }); } }); next(); }

Database Query Optimization

-- Before: Full table scan (1,200ms on 2M rows) SELECT * FROM orders WHERE created_at > NOW() - INTERVAL '7 days'; -- EXPLAIN ANALYZE reveals: -- Seq Scan on orders (rows=2000000, actual time=1200ms) -- Fix 1: Add covering index CREATE INDEX idx_orders_created_at ON orders(created_at DESC) INCLUDE (id, user_id, total, status); -- After: Index scan (8ms) -- Index Scan using idx_orders_created_at (rows=4523, actual time=8ms) -- Fix 2: N+1 query elimination -- Before: 50 separate queries SELECT * FROM order_items WHERE order_id = $1; -- repeated 50 times -- After: Single batched query SELECT * FROM order_items WHERE order_id = ANY($1::uuid[]);

Frontend Bundle Analysis

// next.config.js — Enable bundle analyzer const withBundleAnalyzer = require('@next/bundle-analyzer')({ enabled: process.env.ANALYZE === 'true', }); module.exports = withBundleAnalyzer({ // Dynamic imports for heavy dependencies // Before: import { Chart } from 'chart.js' (200KB) // After: const Chart = dynamic(() => import('chart.js'), { ssr: false }) });

Configuration

OptionTypeDefaultDescription
layersstring[]["api", "database", "frontend"]Profiling targets
slowThresholdnumber1000Response time threshold (ms) for alerts
queryThresholdnumber100Slow query threshold (ms)
sampleRatenumber0.1Fraction of requests to profile (0-1)
enableHeapSnapshotbooleanfalseTake heap snapshots on memory alerts
bundleSizeLimitstring"250kb"Maximum JS bundle size warning

Best Practices

  1. Profile before optimizing — Measure actual bottlenecks with real production data patterns rather than guessing. A query taking 5ms in development may take 500ms against production data volumes. Use EXPLAIN ANALYZE, not EXPLAIN alone, to see actual execution times.

  2. Fix the biggest bottleneck first — If database queries account for 78% of response time, optimizing the serialization layer (6%) will have negligible user-visible impact. Sort bottlenecks by contribution to total latency and address them in order.

  3. Benchmark before and after every change — Record precise metrics before applying an optimization, apply the single change, then re-measure. This confirms the optimization actually helped and quantifies the improvement for your team.

  4. Watch for N+1 queries obsessively — The single most common performance issue in web applications is fetching related data in a loop. Use query logging to count queries per request. If the count grows with data, you have an N+1 problem.

  5. Set performance budgets in CI — Add automated checks that fail the build if bundle size exceeds 250KB, API response time exceeds 500ms, or Lighthouse performance score drops below 90. Catching regressions early prevents gradual degradation.

Common Issues

Memory usage grows steadily over hours — This indicates a memory leak, typically from event listeners not being removed, closures holding references to large objects, or caches without eviction policies. Take heap snapshots 5 minutes apart, then compare retained object counts to identify what is accumulating. Common culprits: global arrays, uncleared intervals, and connection pools without limits.

Event loop delay spikes causing timeout errors — Synchronous operations blocking the event loop for more than 100ms cause cascading delays. Identify blocking code with perf_hooks.monitorEventLoopDelay() and move heavy computation to worker threads. Common sources: JSON.parse on large payloads, synchronous file operations, and CPU-intensive loops without yielding.

Database query plan changes after data growth — A query that used an index scan on 10K rows switches to a sequential scan on 1M rows because the query planner decides the index is no longer selective enough. Run ANALYZE to update table statistics, check that random_page_cost reflects your storage (lower for SSDs), and consider partial indexes for frequently filtered columns.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates