Performance Profiling for Node.js, Python, and Go Applications: A Complete Guide
The Performance Profiler skill provides a systematic, language-agnostic workflow to identify CPU, memory, and I/O bottlenecks using zero-instrumentation tools like clinic, py-spy, and go tool pprof, ensuring production code remains untouched during analysis.
This guide explores the Performance Profiler skill from the alirezarezvani/claude-skills repository, which standardizes performance optimization across backend stacks. It implements a rigorous measure → profile → optimize → re-measure cycle documented in docs/skills/engineering/performance-profiler.md to deliver consistent, data-driven improvements for Node.js, Python, and Go services.
The Performance Profiler Architecture
The skill enforces a five-phase workflow that prevents false positives and builds a documented performance budget for CI pipelines.
The Five-Phase Workflow
- Baseline Measurement – Capture latency, error-rate, RPS, and memory usage using
curlloops or k6 scripts before any code change. - Profiling Phase – Execute external profiling tools that attach to running processes without instrumentation.
- Analysis – Render flamegraphs in Chrome DevTools or
speedscope.appand inspect heap snapshots to locate hot paths, GC pressure, or memory leaks. - Optimization – Apply targeted fixes such as index creation, query batching, or dynamic imports.
- Re-measurement – Run the identical load-test suite and compare metrics side-by-side using the built-in Markdown template.
The architecture emphasizes single-change isolation: modify one component at a time, re-run the profiler, and record delta values. This methodology ensures that every optimization is validated against a concrete baseline.
Node.js Performance Profiling
Node.js profiling leverages the Clinic.js suite and custom scripts to analyze CPU usage and heap allocation without modifying application logic.
CPU Analysis with clinic flame
The clinic tool generates flamegraphs that visualize V8 CPU consumption. Execute the following commands from docs/skills/engineering/performance-profiler.md:
# Install once globally
npm install -g clinic
# Run a flamegraph while the server handles load
clinic flame -- node dist/server.js &
autocannon -c 50 -d 30 http://localhost:3000/api/tasks
The output produces clinic-flamegraph.html, revealing which functions dominate execution time. For event-loop diagnostics, combine this with blocked-at to log stalls.
Memory Leak Detection
Use clinic heapprofiler for heap snapshots and the repository's scripts/memory-profile.mjs for automated regression testing. The script measures RSS and heap usage before and after forced garbage collection:
// scripts/memory-profile.mjs
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
import fs from 'fs';
function formatBytes(b) { return (b/1024/1024).toFixed(2)+' MB'; }
function measure(label) {
const m = process.memoryUsage();
console.log(`\n[${label}] RSS:${formatBytes(m.rss)} HeapUsed:${formatBytes(m.heapUsed)}`);
return m;
}
const base = measure('Baseline');
// ... run workload ...
global.gc?.(); // start node with --expose-gc
measure('After GC');
Execute with node --experimental-vm-modules --expose-gc scripts/memory-profile.mjs. A heap growth exceeding 10% after GC indicates a potential leak.
Python Performance Profiling
Python profiling in this skill relies on external sampling and deterministic analysis tools that require no code rewrites.
Live CPU Sampling with py-spy
py-spy attaches to a running process (e.g., FastAPI/Uvicorn) to generate flamegraphs without restarting the interpreter:
pip install py-spy
# Attach to a live process (PID 1234)
py-spy record -o flamegraph.svg --pid 1234 --duration 30
Open flamegraph.svg in a browser to identify which functions dominate CPU time. This approach is ideal for production environments where stopping the service is unacceptable.
Deterministic and Memory Profiling
For detailed function-level timing, use cProfile. For line-by-line memory usage analysis, implement memory_profiler as referenced in docs/skills/engineering/performance-profiler.md. These tools complement py-spy by providing deterministic data for local development and granular memory allocation tracking.
Go Performance Profiling
Go’s profiling capabilities are built into the standard library, requiring only minimal import changes to expose HTTP endpoints.
Built-in pprof Endpoints
Import net/http/pprof in your main.go to automatically register debug handlers:
package main
import (
_ "net/http/pprof"
"log"
"net/http"
)
func main() {
go func() {
log.Println(http.ListenAndServe(":6060", nil))
}()
// ... rest of application ...
}
Capturing and Visualizing Profiles
Fetch and visualize profiles using go tool pprof:
# Capture a 30-second CPU profile and open web UI
go tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile?seconds=30
The web interface displays flamegraphs and call graphs for hot Goroutines. Heap profiles are available at /debug/pprof/heap using the same tool.
Database Query Optimization
The skill integrates SQL analysis across all three languages. Use EXPLAIN (ANALYZE, BUFFERS) to pinpoint slow queries and detect N+1 patterns. For ORM-based applications (Django, Drizzle), enable query logging to identify redundant database round-trips before they reach production.
Load Testing with k6
Load testing validates profiling results under realistic traffic. The repository includes tests/load/api-load-test.js, a k6 scenario compatible with Node.js, Python, and Go backends:
// tests/load/api-load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate, Trend } from 'k6/metrics';
export const options = {
stages: [
{ duration: '30s', target: 10 },
{ duration: '1m', target: 50 },
{ duration: '2m', target: 50 },
{ duration: '30s', target: 100 },
{ duration: '1m', target: 50 },
{ duration: '30s', target: 0 },
],
thresholds: {
http_req_duration: ['p(95)<500', 'p(99)<1000'],
errors: ['rate<0.01'],
},
};
const errorRate = new Rate('errors');
export default function () {
const res = http.get(`${__ENV.BASE_URL}/api/tasks`);
check(res, { 'status 200': (r) => r.status === 200 }) || errorRate.add(1);
sleep(0.5);
}
Run the test with:
k6 run tests/load/api-load-test.js --env BASE_URL=http://localhost:3000
This script records latency percentiles (p95, p99), error rates, and custom trends, providing the metrics needed for the before/after comparison phase.
Before/After Measurement and Reporting
The skill provides Markdown templates to document performance deltas. After optimization, teams re-run the identical k6 suite and populate the template with new metrics, creating an audit trail for CI/CD performance budgets. This reporting step is defined in engineering/performance-profiler/SKILL.md and referenced throughout the documentation.
Summary
- The Performance Profiler skill implements a measure → profile → optimize → re-measure cycle that prevents regressions through single-change isolation.
- Node.js applications use
clinic flameandclinic heapprofilerfor CPU and heap analysis, supplemented byscripts/memory-profile.mjsfor leak detection. - Python services leverage
py-spyfor live sampling andmemory_profilerfor line-by-line allocation tracking without code modification. - Go programs utilize the built-in
net/http/pprofpackage andgo tool pproffor comprehensive CPU and heap visualization. - All languages share k6 load-testing scenarios from
tests/load/api-load-test.jsto validate improvements against established baselines. - Built-in Markdown templates ensure every optimization is documented and comparable across CI runs.
Frequently Asked Questions
Do I need to modify my application code to use these profiling tools?
No. The majority of tools recommended in docs/skills/engineering/performance-profiler.md run externally. py-spy attaches to live PIDs, clinic wraps your process, and Go’s pprof endpoints expose data via HTTP without changing business logic. Only the Go implementation requires adding the net/http/pprof import, which exposes debug endpoints without affecting runtime behavior.
What is the recommended load testing tool across all three languages?
k6 is the standard load-testing tool for Node.js, Python, and Go applications within this skill. The repository provides tests/load/api-load-test.js, a JavaScript-based k6 script that works with any HTTP backend, recording latency percentiles and error rates to validate profiling results.
How do I detect memory leaks in Node.js applications?
Use the scripts/memory-profile.mjs utility to measure heap growth before and after forced garbage collection. Run the script with node --expose-gc to enable global.gc(). If heap usage exceeds the baseline by more than 10% after GC, the skill flags this as a potential leak requiring deeper analysis with clinic heapprofiler.
Can I profile a running Python process without restarting it?
Yes. py-spy supports attaching to live processes by PID using the command py-spy record -o flamegraph.svg --pid <PID> --duration 30. This reads the Python process memory from /proc without requiring code instrumentation or service interruption, making it safe for production environments.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →