Skip to main content
Version: 6.x (latest)

Optimize performance with CPU profiles

Capture CPU profiles of a running process in the N|Solid Console, analyze them in the Console or in Chrome DevTools, and use source maps to map profiles back to your original code.

CPU profiling shows where your application spends its time, so you can find opportunities to improve the speed and capacity of your Node.js processes. CPU profiles use low-overhead sampling, so you can run them for long periods. Most of the overhead comes from the V8 profiler and from the N|Solid Agent sending the profile.

Capture a CPU profile in the N|Solid Console​

The N|Solid Console lets you capture and analyze a profile in one place. This helps when you need a series of profiles, because you don't have to switch between tools. The Console also keeps a history of your profiles, so you can move between them while you troubleshoot.

  1. Select the process you want to profile.
  2. On the process details page, click the New CPU Profile icon. "New profile"
  3. In the New CPU Profile dialog, set the Profile Duration with the slider or the input field. Choose Seconds or Minutes; the duration can be from 1 second to 10 minutes (600 seconds).
  4. Select the thread to profile. Thread 0 is the main thread; the others are worker threads.
  5. Click Start Profile. "Run profile"
  6. When the profile is complete, a notification appears at the top of the page. Click View Profile to open it. "Flame Graph"

If your application exits before the profile is complete, N|Solid tries to save the profile data collected so far. If it succeeds, the profile appears in the Assets view.

note

The New CPU Profile icon is disabled if assets are disabled for the process (for example, with NSOLID_ASSETS_ENABLED=0), or if your role doesn't have permission to generate CPU profiles.

Analyze a profile in the N|Solid Console​

Each visualization shows the unique set of stack traces captured during the profile. The area of each stack frame shows the share of time spent in that function compared to its parent.

Use the view options in the profile view to switch between visualizations:

  • Flame Graph: the y-axis shows the function calls that make up each stack trace. Width on the x-axis shows the share of total samples; it is not a timeline.
  • Top Table: a table of all functions with their self time and total time. Click a column heading, such as Self, to sort by it.
  • Both: the table and the flame graph side by side.

Use the Search... box to find functions by name. To see who calls a function and what it calls, click the sandwich view button on its row in the table; the Callers and Callees panes appear.

Hover over a frame to see the function it represents.

Find slow functions​

Long-running functions show up as:

  • wide frames in the Flame Graph
  • high self time in the Top Table

The height of a stack (how many functions deep it goes) doesn't indicate a time problem on its own. Focus on width and self time.

AI reports​

The N|Solid Copilot can analyze a CPU profile for you. Open the profile and click AI Report. The report highlights problems such as functions with high self time or high call volume. When the Copilot identifies a problem function, it asks for access to the source file that contains it and tries to write an improved version. It checks candidate rewrites with the NodeSource benchmarking service, and when it finds a faster version, it suggests a code snippet to replace the original function.

With the GitHub MCP Server integration, the Copilot can also open pull requests for the issues it finds in a CPU profile.

AI Report Button

note

AI Report requires the AI service permission for your role, and the N|Solid MCP Server must be configured in Settings > Integrations > MCP Integrations. The button isn't available for continuous CPU profiles.

Analyze a profile in Chrome DevTools​

You can also open a CPU profile in Chrome DevTools:

  1. In the profile view, click Download Raw Profile to download the .cpuprofile file.
  2. Open Google Chrome.
  3. Open Chrome DevTools: press F12 (or Ctrl+Shift+I; Cmd+Option+I on macOS), or open the Chrome menu and select More tools > Developer tools.
  4. Open the Performance panel.
  5. Click Load profile (the up-arrow icon) and select the downloaded .cpuprofile file.
  6. The profile appears as a timeline in the Performance panel.
  7. Use the Bottom-up and Call tree tabs below the timeline to see where time was spent.

Besides function execution times, the timeline shows which functions were on the stack each time the process was sampled.

Capture a profile with the CLI​

The N|Solid command-line interface (CLI) is a quick way to pull profiles from remote processes for local analysis. See the profile command in the CLI reference.

Understand CPU profiles​

Self time and total time​

A CPU profile records the function call stack at each sample. For example, if foo() calls bar(), and a sample is taken while bar() is running, the stack shows that foo() called bar(). Because several samples may be taken while bar() runs, the profile gives an approximate indication of how long bar() took. Samples taken before and after those capture foo(), and so on down the stack.

From this data, the profiler works out how much time was spent in foo() itself, and how much in bar(). Every function has two values: self time and total time. If foo() calls only bar(), then the self time of foo() plus the total time of bar() equals the total time of foo():

function foo() {
// ... processing that takes a lot of time but calls no other functions ...
bar()
// ... processing that takes a lot of time but calls no other functions ...
}

function bar() {
// ...
}

foo() total time = foo() self time + bar() total time

note

Total time shows which functions are fastest and slowest from start to finish, but it doesn't tell you whether the time was spent in that function or in the functions it called.

Name your functions​

Named functions are easier to spot in CPU profiles. Each stack frame in a profile includes the function name and its source location. Anonymous functions usually appear as (anonymous). Sometimes V8 can infer a name for a function, but where you can, give functions names so you can find them in a profile.

For example, this anonymous function calls busyFunction():

setInterval(function () { busyFunction() }, 1000)

In a CPU profile, busyFunction() appears to be called by (anonymous). To make the caller easier to find, name it:

setInterval(function busyFunctionCaller () { busyFunction() }, 1000)

Now the profile shows that busyFunction() is called by busyFunctionCaller().

For cleaner code and clearer profiles, you can move the function to the same scope where it's used:

setInterval(busyFunctionCaller, 1000)
// ...
function busyFunctionCaller () {
busyFunction()
}

Because JavaScript function declarations are hoisted to the top of their scope, you can reference busyFunctionCaller before it's defined.

Source maps​

If you use TypeScript, a bundler, or a transpiler, the code that runs isn't the code you wrote, which makes CPU profiles hard to read. Source maps translate locations in the compiled code back to your original source.

To resolve a CPU profile with source maps in the N|Solid Console:

  1. Open the CPU profile. The Sourcemaps: control in the profile header shows Upload File when no source maps are attached, and View File when they are.
  2. Click Upload File to open the Sourcemap Upload dialog.
  3. Compress the build output folder that contains your source maps into a .zip file, for example zip -r dist.zip ./dist (or Compress-Archive ./dist dist.zip in PowerShell). The source maps must come from the same build as the profiled code.
  4. Upload the .zip file. The Console resolves the profile and shows a summary of resolved and unresolved locations.

The Console can also fetch source maps automatically from external storage, such as an HTTPS endpoint or an S3-compatible bucket. For setup instructions, and for how Sourcemap Resolution per Profile in the process's configuration controls whether profiles share source maps, see External sourcemap retrieval.

NodeSource Support