profiling-optimization

安装量: 128
排名: #6741

安装

npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill profiling-optimization

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();

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(name: string, fn: () => Promise): Promise { 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); });

  1. 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 { 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');

  1. 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')

  1. Benchmarking class Benchmark { async run( name: string, fn: () => Promise, iterations: number = 1000 ): Promise { 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 }>, iterations: number = 1000 ): Promise { 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; } } ]);

  1. 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));

  1. 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 { private cache = new Map(); 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);
}

} }

  1. Lazy Loading class LazyValue { 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 0x Flame Graph Profiler Chrome DevTools Profiling Python cProfile

返回排行榜