What a flame graph is useful for
A flame graph shows which functions are consuming CPU time and how they relate to one another in the call stack. The most saturated (orange) bars represent CPU-heavy functions. Clicking an element zooms in on that section. Flame graphs are generated fromperf output — not a Node.js-specific tool.
While it is the most powerful way to visualize CPU time spent, it may have
issues with how JavaScript code is optimized in Node.js 8 and above. See
perf output issues for details.
How to create a flame graph
Use a pre-packaged tool
For a single-step solution that produces a flame graph locally, use 0x:Create a flame graph with system perf tools
This approach gives you full control over each step.Install perf
Install Try running
perf — usually available through the linux-tools-common package:perf. If it complains about missing kernel modules, install
those too.Run Node.js with perf enabled
See perf output issues for tips specific to your
Node.js version.Disregard warnings unless they say you cannot run
perf due to missing
packages. Warnings about kernel module samples are expected and can be
ignored.Generate the data file
Export the perf data:It is useful to filter out Node.js internal functions
for a more readable graph.
Preview or generate the flame graph
- Browser preview (no setup)
- Local with FlameGraph tools
Upload the generated
perfs.out file to flamegraph.com
to visualize the flame graph directly in your browser.Sampling a running process
This is useful for recording flame graph data from an already-running process that you do not want to interrupt — for example, a production process with a hard-to-reproduce issue.| Option | Explanation |
|---|---|
-F99 | Profiling frequency: 99 samples per second. Increase for more precision; lower values produce less output. |
-p | PID of the process to profile |
-- sleep 3 | Keeps perf running for 3 seconds. perf runs for the life of the command passed to it. |
Filtering out Node.js internal functions
Usually, you want to focus on the performance of your own code. Filter out Node.js and V8 internal functions to make the graph easier to read:If your flame graph looks odd or something seems missing in a key function,
try generating it without the filters. You may have a rare case of an issue
within Node.js itself.
Node.js profiling options
--perf-basic-prof and --perf-basic-prof-only-functions are the two flags
useful for debugging your JavaScript code. Other options are used for profiling
Node.js itself, which is outside the scope of this guide.
| Flag | Effect |
|---|---|
--perf-basic-prof | Always writes to /tmp/perf-PID.map. Lower overhead than full profiling, but can cause unbounded disk growth. |
--perf-basic-prof-only-functions | Produces less output than --perf-basic-prof. The lowest-overhead option, suitable for production. |
Without these options you will still get a flame graph, but most bars will
be labeled
v8::Function::Call instead of showing your actual function names.perf output issues
Node.js 8.x V8 pipeline changes
Node.js 8.x and above ships with new optimizations to the JavaScript compilation pipeline in the V8 engine (Turbofan), which makes function names/references sometimes unreachable forperf.
The result is that you might see ByteCodeHandler: where you would expect
function names.
0x has mitigations for this built in.
For details, see:
Node.js 10+
Node.js 10.x addresses the Turbofan issue with the--interpreted-frames-native-stack flag:
Broken labels in the flame graph
If you see labels like this:perf you are using was not compiled with demangle support.
See this Ubuntu bug for more information.