Find the Hot Function Before You Optimise the Wrong Thing
Profiling Node.js Algorithms
Use node --prof, --cpu-prof, and clinic.js to generate flamegraphs that reveal exactly which function in your algorithm is consuming the most CPU — so you optimise the bottleneck, not a guess.
What you'll learn
- Generate a V8 profiling log with node --prof and convert it to readable output
- Capture a CPU profile with --cpu-prof and open it in Chrome DevTools
- Interpret a flamegraph to find the widest self-time bar
The first rule of optimisation is measure before you change. Intuition about where time is spent is often wrong. A flamegraph shows the call stack sampled thousands of times per second — the widest bars are where the CPU actually is.
node —prof (V8 Built-in Profiler)
--prof writes a binary log. --prof-process converts it to readable text.
// algo.mjs — the algorithm to profile
function hasDuplicates(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) return true;
}
}
return false;
}
const data = Array.from({ length: 10_000 }, () =>
Math.floor(Math.random() * 20_000),
);
console.log(hasDuplicates(data)); // Shell commands (not JS — shown as comments for context)
// node --prof algo.mjs
// node --prof-process isolate-*.log > processed.txt
// grep -A 20 "[Summary]" processed.txt The summary section shows which functions consumed the most ticks. A nested loop will dominate immediately.
—cpu-prof (Chrome DevTools Format)
--cpu-prof writes a .cpuprofile file you can drag into Chrome DevTools or
VS Code’s built-in profiler for a visual flamegraph.
// node --cpu-prof --cpu-prof-interval=100 algo.mjs
// Opens algo.mjs.cpuprofile in Chrome DevTools → Performance → Load profile Set --cpu-prof-interval in microseconds (default 1000 µs = 1 ms). Lower
values give finer resolution but larger files.
clinic.js for Richer Diagnostics
clinic is an open-source toolkit that wraps --prof and adds interactive
HTML flamegraphs, event-loop delay charts, and heap bubble charts.
// Install once globally
// npm install -g clinic
// Doctor — detects event-loop lag, memory growth, GC pressure
// clinic doctor -- node algo.mjs
// Flame — generates an interactive flamegraph
// clinic flame -- node algo.mjs clinic flame groups frames by module and highlights Node internals vs your
code, making it easy to spot whether the bottleneck is in your algorithm or in
a library you depend on.
Reading a Flamegraph
| Feature | What it means |
|---|---|
| Width of a bar | Total time spent in that function (including callees) |
| Self-time (colour shade) | Time spent inside the function, excluding callees |
| Tall stack | Deep recursion — watch for stack overflows |
| Plateau at the top | The function that is actually doing the work |
The optimisation target is the widest bar with the most self-time near the top of the stack. Everything below it is just the call chain leading there.
Up Next
After you find the slow function, check whether it is also leaking memory — heap snapshots reveal allocations that never get collected.
Memory Tuning and Heap Snapshots →