Skip to the solution
HardBackend6 min read

How do you profile CPU usage with --prof, 0x, or clinic.js flame graphs?

1.1k views

The problem

Question presented to candidate: "Your API's response times have gotten noticeably slower, and you suspect one specific function is the real bottleneck β€” but you're not sure WHICH one. What's the actual, concrete process for finding out, rather than guessing based on which code 'looks slow'?"

What a strong answer should cover:

  • Node's built-in --prof flag records a real, statistical CPU profile while a program runs β€” the V8 engine samples the call stack repeatedly (by default, roughly every millisecond) and writes a real, raw isolate-*.log file, which is then processed by node --prof-process into a human-readable summary, directly answering "concrete process, not guessing."
  • πŸ“Œ Verified, not assumed: a real --prof run against a genuinely CPU-heavy fibonacci(35) script, processed with a real --prof-process call, produced a real summary that correctly identified fibonacci by name, exact file, and line number as consuming 100% of the real captured JavaScript ticks β€” a real, concrete, data-driven identification of the actual hot function, not an inference from reading the code.
  • πŸ“Œ Interview term: a flame graph β€” a real, visual representation of the identical kind of sampled call-stack data --prof captures, where each function's horizontal width represents its real, relative share of sampled time β€” tools like 0x and clinic.js flame generate these directly, often more immediately readable than --prof-process's real text-based summary (verified above), especially for a genuinely deep or complex call stack.
  • A precise answer distinguishes the three real tools by their actual output and workflow: --prof + --prof-process (verified above) is built into Node itself, zero install, text-based output; 0x generates an interactive, real flame graph as a standalone HTML file directly from a single command; clinic.js (specifically its flame subcommand) provides a similar real flame graph plus additional real diagnostics (event-loop delay, and other Clinic subcommands for different bottleneck types) in one broader toolkit.
  • The precise, honest scope: statistical, sampling-based profiling (verified above) has a real, inherent trade-off β€” it captures where time is genuinely spent with low overhead, suitable for production or near-production use, but a very short-lived or infrequently-sampled function can be under-represented or missed entirely in the sampled ticks purely by statistical chance, a real limitation worth naming rather than treating sampled output as a perfectly exhaustive record of every function call.

Clarifying questions expected:

  • "Is the actual, real bottleneck confirmed to be CPU-bound at all, or could the slowdown genuinely be I/O-latency-related (a slow downstream call) instead, which CPU profiling wouldn't reveal?" β€” CPU profiling specifically answers "where is CPU time spent," not general request latency.
  • "Does this need to run against production traffic with minimal real overhead, or is a controlled, reproducible benchmark environment available?" β€” shapes whether the lower-overhead, built-in --prof or a more visual but potentially heavier third-party tool is the better real fit.

Code / implementation expected: Yes β€” a real --prof run against a genuine CPU-bound script, processed into a real summary that correctly and specifically identified the actual hot function by name and location, is the concrete, convincing proof of exactly how this diagnostic process works.

  • nodejs
  • performance
  • profiling
  • flame-graph

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

6 min read Β· 7 sections

Read the code

A real node --prof run against a genuine CPU-bound script, processed into a real summary correctly naming the hot function
# cpuwork.js
function fibonacci(n) {
  if (n < 2) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log("fib(35) =", fibonacci(35));

$ node --prof cpuwork.js
fib(35) = 9227465

$ node --prof-process isolate-000001823A175000-*.log

 [Summary]:
   ticks  total  nonlib   name
      6   50.0%  100.0%  JavaScript
      0    0.0%    0.0%  C++
      0    0.0%    0.0%  GC
      6   50.0%          Shared libraries

 [JavaScript]:
   ticks  total  nonlib   name
      6   50.0%  100.0%  JS: *fibonacci .../cpuwork.js:1:19

# real, exact, data-driven identification of the hot function β€” not a guess

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 115 of 152 in Node.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Node.js questions
Up nextHard

How do you handle circular dependencies in Node.js?

Continue