Claude Code Plugins

Community-maintained marketplace

Feedback

profiling-optimization

@aj-geddes/useful-ai-prompts
4
0

Profile application performance, identify bottlenecks, and optimize hot paths using CPU profiling, flame graphs, and benchmarking. Use when investigating performance issues or optimizing critical code paths.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name profiling-optimization
description Profile application performance, identify bottlenecks, and optimize hot paths using CPU profiling, flame graphs, and benchmarking. Use when investigating performance issues or optimizing critical code paths.

Profiling & Optimization

Overview

Profile code execution to identify performance bottlenecks and optimize critical paths using data-driven approaches.

When to Use

  • Performance optimization
  • Identifying CPU bottlenecks
  • Optimizing hot paths
  • Investigating slow requests
  • Reducing latency
  • Improving throughput

Implementation Examples

1. Node.js Profiling

import { performance, PerformanceObserver } from 'perf_hooks';

class Profiler {
  private marks = new Map<string, number>();

  mark(name: string): void {
    this.marks.set(name, performance.now());
  }

  measure(name: string, startMark: string): number {
    const start = this.marks.get(startMark);
    if (!start) throw new Error(`Mark ${startMark} not found`);

    const duration = performance.now() - start;
    console.log(`${name}: ${duration.toFixed(2)}ms`);

    return duration;
  }

  async profile<T>(name: string, fn: () => Promise<T>): Promise<T> {
    const start = performance.now();

    try {
      return await fn();
    } finally {
      const duration = performance.now() - start;
      console.log(`${name}: ${duration.toFixed(2)}ms`);
    }
  }
}

// Usage
const profiler = new Profiler();

app.get('/api/users', async (req, res) => {
  profiler.mark('request-start');

  const users = await profiler.profile('fetch-users', async () => {
    return await db.query('SELECT * FROM users');
  });

  profiler.measure('total-request-time', 'request-start');

  res.json(users);
});

2. Chrome DevTools CPU Profile

import inspector from 'inspector';
import fs from 'fs';

class CPUProfiler {
  private session: inspector.Session | null = null;

  start(): void {
    this.session = new inspector.Session();
    this.session.connect();

    this.session.post('Profiler.enable');
    this.session.post('Profiler.start');

    console.log('CPU profiling started');
  }

  async stop(outputFile: string): Promise<void> {
    if (!this.session) return;

    this.session.post('Profiler.stop', (err, { profile }) => {
      if (err) {
        console.error('Profiling error:', err);
        return;
      }

      fs.writeFileSync(outputFile, JSON.stringify(profile));
      console.log(`Profile saved to ${outputFile}`);

      this.session!.disconnect();
      this.session = null;
    });
  }
}

// Usage
const cpuProfiler = new CPUProfiler();

// Start profiling
cpuProfiler.start();

// Run code to profile
await runExpensiveOperation();

// Stop and save
await cpuProfiler.stop('./profile.cpuprofile');

3. Python cProfile

import cProfile
import pstats
from pstats import SortKey
import io

class Profiler:
    def __init__(self):
        self.profiler = cProfile.Profile()

    def __enter__(self):
        self.profiler.enable()
        return self

    def __exit__(self, *args):
        self.profiler.disable()

    def print_stats(self, sort_by: str = 'cumulative'):
        """Print profiling statistics."""
        s = io.StringIO()
        ps = pstats.Stats(self.profiler, stream=s)

        if sort_by == 'time':
            ps.sort_stats(SortKey.TIME)
        elif sort_by == 'cumulative':
            ps.sort_stats(SortKey.CUMULATIVE)
        elif sort_by == 'calls':
            ps.sort_stats(SortKey.CALLS)

        ps.print_stats(20)  # Top 20
        print(s.getvalue())

    def save_stats(self, filename: str):
        """Save profiling data."""
        self.profiler.dump_stats(filename)

# Usage
with Profiler() as prof:
    # Code to profile
    result = expensive_function()

prof.print_stats('cumulative')
prof.save_stats('profile.prof')

4. Benchmarking

class Benchmark {
  async run(
    name: string,
    fn: () => Promise<any>,
    iterations: number = 1000
  ): Promise<void> {
    console.log(`\nBenchmarking: ${name}`);

    const times: number[] = [];

    // Warmup
    for (let i = 0; i < 10; i++) {
      await fn();
    }

    // Actual benchmark
    for (let i = 0; i < iterations; i++) {
      const start = performance.now();
      await fn();
      times.push(performance.now() - start);
    }

    // Statistics
    const sorted = times.sort((a, b) => a - b);
    const min = sorted[0];
    const max = sorted[sorted.length - 1];
    const avg = times.reduce((a, b) => a + b, 0) / times.length;
    const p50 = sorted[Math.floor(sorted.length * 0.5)];
    const p95 = sorted[Math.floor(sorted.length * 0.95)];
    const p99 = sorted[Math.floor(sorted.length * 0.99)];

    console.log(`  Iterations: ${iterations}`);
    console.log(`  Min: ${min.toFixed(2)}ms`);
    console.log(`  Max: ${max.toFixed(2)}ms`);
    console.log(`  Avg: ${avg.toFixed(2)}ms`);
    console.log(`  P50: ${p50.toFixed(2)}ms`);
    console.log(`  P95: ${p95.toFixed(2)}ms`);
    console.log(`  P99: ${p99.toFixed(2)}ms`);
  }

  async compare(
    implementations: Array<{ name: string; fn: () => Promise<any> }>,
    iterations: number = 1000
  ): Promise<void> {
    for (const impl of implementations) {
      await this.run(impl.name, impl.fn, iterations);
    }
  }
}

// Usage
const bench = new Benchmark();

await bench.compare([
  {
    name: 'Array.filter + map',
    fn: async () => {
      const arr = Array.from({ length: 1000 }, (_, i) => i);
      return arr.filter(x => x % 2 === 0).map(x => x * 2);
    }
  },
  {
    name: 'Single loop',
    fn: async () => {
      const arr = Array.from({ length: 1000 }, (_, i) => i);
      const result = [];
      for (const x of arr) {
        if (x % 2 === 0) {
          result.push(x * 2);
        }
      }
      return result;
    }
  }
]);

5. Database Query Profiling

import { Pool } from 'pg';

class QueryProfiler {
  constructor(private pool: Pool) {}

  async profileQuery(query: string, params: any[] = []): Promise<{
    result: any;
    planningTime: number;
    executionTime: number;
    plan: any;
  }> {
    // Enable timing
    await this.pool.query('SET track_io_timing = ON');

    // Get query plan
    const explainResult = await this.pool.query(
      `EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) ${query}`,
      params
    );

    const plan = explainResult.rows[0]['QUERY PLAN'][0];

    // Execute actual query
    const start = performance.now();
    const result = await this.pool.query(query, params);
    const duration = performance.now() - start;

    return {
      result: result.rows,
      planningTime: plan['Planning Time'],
      executionTime: plan['Execution Time'],
      plan
    };
  }

  formatPlan(plan: any): string {
    let output = 'Query Plan:\n';
    output += `Planning Time: ${plan['Planning Time']}ms\n`;
    output += `Execution Time: ${plan['Execution Time']}ms\n\n`;

    const formatNode = (node: any, indent: number = 0) => {
      const prefix = '  '.repeat(indent);
      output += `${prefix}${node['Node Type']}\n`;
      output += `${prefix}  Cost: ${node['Total Cost']}\n`;
      output += `${prefix}  Rows: ${node['Actual Rows']}\n`;
      output += `${prefix}  Time: ${node['Actual Total Time']}ms\n`;

      if (node.Plans) {
        node.Plans.forEach((child: any) => formatNode(child, indent + 1));
      }
    };

    formatNode(plan.Plan);
    return output;
  }
}

// Usage
const profiler = new QueryProfiler(pool);

const { result, planningTime, executionTime, plan } = await profiler.profileQuery(
  'SELECT * FROM users WHERE age > $1',
  [25]
);

console.log(profiler.formatPlan(plan));

6. Flame Graph Generation

# Generate flame graph using 0x
npx 0x -o flamegraph.html node server.js

# Or using clinic.js
npx clinic doctor --on-port 'autocannon localhost:3000' -- node server.js
npx clinic flame --on-port 'autocannon localhost:3000' -- node server.js

Optimization Techniques

1. Caching

class LRUCache<K, V> {
  private cache = new Map<K, V>();
  private maxSize: number;

  constructor(maxSize: number = 100) {
    this.maxSize = maxSize;
  }

  get(key: K): V | undefined {
    if (!this.cache.has(key)) return undefined;

    // Move to end (most recently used)
    const value = this.cache.get(key)!;
    this.cache.delete(key);
    this.cache.set(key, value);

    return value;
  }

  set(key: K, value: V): void {
    // Remove if exists
    if (this.cache.has(key)) {
      this.cache.delete(key);
    }

    // Add to end
    this.cache.set(key, value);

    // Evict oldest if over capacity
    if (this.cache.size > this.maxSize) {
      const oldest = this.cache.keys().next().value;
      this.cache.delete(oldest);
    }
  }
}

2. Lazy Loading

class LazyValue<T> {
  private value?: T;
  private loaded = false;

  constructor(private loader: () => T) {}

  get(): T {
    if (!this.loaded) {
      this.value = this.loader();
      this.loaded = true;
    }
    return this.value!;
  }
}

// Usage
const expensive = new LazyValue(() => {
  console.log('Computing expensive value...');
  return computeExpensiveValue();
});

// Only computed when first accessed
const value = expensive.get();

Best Practices

✅ DO

  • Profile before optimizing
  • Focus on hot paths
  • Measure impact of changes
  • Use production-like data
  • Consider memory vs speed tradeoffs
  • Document optimization rationale

❌ DON'T

  • Optimize without profiling
  • Ignore readability for minor gains
  • Skip benchmarking
  • Optimize cold paths
  • Make changes without measurement

Tools

  • Node.js: 0x, clinic.js, node --prof
  • Python: cProfile, py-spy, memory_profiler
  • Visualization: Flame graphs, Chrome DevTools
  • Database: EXPLAIN ANALYZE, pg_stat_statements

Resources