IntelliJ IDEA 14.1.0 Help

V8 CPU and Memory Profiling

As you may know, V8 is an open-source JavaScript engine developed by Google. It is used in Google Chrome, Chromium, Node.js, and io.js.

V8 has a sampling CPU profiler V8 profiler which is intended for capturing and analyzing CPU profiles and heap snapshots for your Node.js applications. With V8 CPU profiling you can get a better understanding of which parts of your code take up the most CPU time, and how your code is executed and optimized by the V8 JavaScript engine.

You can also open and explore profiles and snapshots captured in Google Chrome DevTools for your client-side code.

On this page:

Why Is Profiling Important

  • A carefully designed algorithm can make your code faster and manage your memory consumption better, even more efficiently than the virtual machine can. Profiling is the way to look inside the execution of your code and prove your assumptions about your design decisions.
  • Profiling is especially relevant for Javascript, which is a powerful language with advanced features like dynamic typing, closures, and even the ability to create code at runtime. Therefore the behavior of the JavaScript engine is quite sophisticated, and there are cases when you really need to go deep into the details of how the engine works. Some of the code patterns you use need being tweaked to allow the JavaScript optimizer to do its work.
  • JavaScript is by no means a simple language to judge if your code manages memory well. Closure memory leaks are a good illustration of the fact that code that looks good and simple may still cause leaks.

Before You Start

  1. Install the Node.js framework version 0.11.0 or higher.
  2. Install and enable the NodeJS plugin as described in Installing, Updating and Uninstalling Repository Plugins and Enabling and Disabling Plugins.

    The plugin is not bundled with IntelliJ IDEA, but it can be installed from the JetBrains plugin repository as described in Installing, Updating and Uninstalling Repository Plugins and Enabling and Disabling Plugins. Once enabled, the plugin is available at the IDE level, that is, you can use it in all your IntelliJ IDEA projects.

  3. Restart IntelliJ IDEA for the changes to take effect.

Preparing for V8 CPU and Memory Heap Profiling

V8 CPU and memory profiling is provided through the tick and v8-profiler packages. To explore a timeline view that shows where V8 is spending time, install the Gnuplot package.

The tick and v8-profiler packages can be installed from IntelliJ IDEA using the Node Package Manager (npm). The Gnuplot package has to be installed outside IntelliJ IDEA, and the installation procedure depends on the operating system you are using.

Installing the tick and v8-profiler Packages

You can install the tick and v8-profiler packages using the Node Package Manager (npm) either in the command line mode or on the Node.Js and NPM page of the Settings dialog box.

To install the tick and V8 Profiler packages globally, do one of the following:

  • In the command line mode, type npm install -g tick, then type npm install -g v8-profiler.
  • Use the Node.Js and NPM page of the Settings dialog box:
    1. Open the Settings dialog box by choosing File | Settings or pressing Ctrl+Alt+S and click Node.js and NPM under Languages & Frameworks.
    2. On the Node.js and NPM page that opens, click Install add in the Packages area.
    3. In the Available Packages dialog box that opens, select the required package (tick or v8-profiler) from the list, possibly using the search field.
    4. Select the Options check box and type -g in the text box next to it to have the packages installed globally and thus make them available from any IntelliJ IDEA project.
    5. Click Install.
    6. When all the packages are installed successfully, close the dialog box. IntelliJ IDEA brings you back to the Node.js and NPM page where the packages are added to the list.

Learn more about installing packages through NPM at Installing and Removing External Software Using Node Package Manager.

Installing the Gnuplot Package

To install the Gnuplot package and be sure that all the required dependencies are installed as well, do one of the following depending on the operating system you are using:

CPU Profiling

With V8 CPU profiling you can get a better understanding of which parts of your code take up the most CPU time, and how your code is executed and optimized by the V8 JavaScript engine.

To identify the processes that consume most of your CPU, you can use two methods: sampling and tracing.

  • When the sampling method is applied, you periodically record stack traces of your application. The periods between records are measured in conventional units referred to as ticks.

    This method does not guarantee very good accuracy or precision for the following reason: snapshots are taken at random moments therefore any function can happen to be recorded in a snapshot. However, sampling can give us a rough picture of where the most of time is spent.

  • When the tracing method is used, we actively record tracing information by ourselves, directly in the code. It is obviously better to get exact measurements of how much time each method took, and also allows to count how many times the traced method was called. The disadvantage of this method is that it comes with bigger result distortion compared to sampling.

Result Distortion. Both sampling and tracing introduce delays into execution and therefore influence the profiling results. With sampling, delays can be estimated as some fixed amount of time for each sampling event and do not introduce greater distortion than the sampling method itself (i.e. the delay is much shorter than the sampling interval). With tracing, the profiling delay depends on the code and the places where we made tracing measurements. For instance, if a traced method is called inside other traced methods numerously, all inner delays will accumulate for the outer method. If so, it may be difficult to separate the execution time from tracing distortion.

Usually we use sampling and tracing methods together. We start with sampling to get an idea of which parts of our code take the most time, and then instrument the code with tracing calls to zero on the issues.

Measurements are made not only for the work of your code, but also activities performed by the engine itself, such as compilation, calls of system libraries, optimization, and garbage collection. The following time metrics are made for execution of functions themselves and for performing activities:

  • Total: the number of ticks (the time) during which a function was executed or an activity was performed.
  • Total%: the ratio of a function/activity execution time to the entire time when measurements were made.
  • Self: the pure execution time of a function/activity itself, without the time spent on executing functions called by it.
  • Self%: the ratio of the pure execution time of a function/activity to the entire time when the measurements were made.
  • Of Parent: the ratio of the pure execution time of a function to the execution time of the function that called it (Parent).

Configuring CPU Profiling

To invoke V8 CPU profiling on application start, you need to specify additional settings in the Node.js run configuration according to which the application will be launched.

  1. Choose Run | Edit Configuration on the main menu. Alternatively, click Shift+Alt+F10 and select Edit Configuration from the pop-up menu.
  2. From the list, choose the Node.js run configuration to activate CPU Profiling in or create a new configuration as described in Running and Debugging Node.Js.
  3. Switch to the V8 Profiling pane and specify the following:
    1. Select the Record CPU profiling info check box.
    2. In the Log folder field, specify the folder to store recorded logs in. Profiling data are stored in V8 log files isolate-<session number>.
    3. Specify the tick package to use. Choose the relevant package from the Tick package drop-down list or click the browseButton button next to it and choose the package in the dialog box that opens.
    4. To explore a timeline view that shows where V8 is spending time, specify the location of the Gnuplot executable file.

Collecting CPU Profiling Information

  1. Select the run configuration from the list on the main tool bar and then choose Run | Run <configuration name> on the main menu or click the Run toolbar button run.png.
  2. When the scenario that you need to profile is executed, stop the process by clicking stop.png on the tool bar of the Run tool window.

V8 log file will be processed by V8 scripts to calculate averaged call traces. IntelliJ IDEA opens the V8 Profiling Tool Window.

Analyzing CPU Profiling Information

Analyzing the profiling logs is available after the process stops because currently stopping and restarting profiling during execution of an application is not supported.

The collected profiling data is displayed in the V8 Profiling Tool Window which IntelliJ IDEA opens automatically when you stop your application. If the window is already opened and shows the profiling data for another session, a new tab is added. Tabs that were opened automatically are named after the run configurations that control execution of the applications and collecting the profiling data.

If you want to open and analyze some previously saved profiling data, choose V8 Profiling - Analyze V8 Profiling Log on the main menu and select the relevant V8 log file isolate-<session number>. IntelliJ IDEA creates a separate tab with the name of the log file.

Exploring Call Tress

Based on the collected profiling data, IntelliJ IDEA builds three call trees and displays each of them in a separate pane. Having several call trees provides the possibility to analyze the application execution from two different points of view: on the one hand, which calls were time consuming ("heavy"), and on the other hand, "who called whom".

  • The Top Calls pane shows a list of performed activities sorted in the descending order by the Self metrics. For each activity IntelliJ IDEA displays its Total, Total%, and Self% metrics. For each function call, IntelliJ IDEA displays the name of the file, the line, and the column where the function is defined.
    v8ProfilerCPUTopCalls.png
  • The Bottom-up pane also shows the performed activities sorted in the descending order by the Self metrics. Unlike the Top Calls pane, the Bottom-up pane shows only the activities with the Total% metrics above 2 and the functions that called them. This is helpful if you encounter a heavy function and want to find out where it was called from.

    For each activity IntelliJ IDEA displays its execution time in ticks and the Of Parent metrics. For each function call, IntelliJ IDEA displays the name of the file, the line, and the column where the function is defined.

  • The Top-down pane shows the entire call hierarchy with the functions that are execution entry points at the top. For each activity IntelliJ IDEA displays its Total, Total%, Self, and Self% metrics. For each function call, IntelliJ IDEA displays the name of the file, the line, and the column where the function is defined. Some of the functions may have been optimized by V8, see Optimizing for V8 for details.
    • The functions that have been optimized are marked with an asterisk (*) before the function name.
    • The functions that possibly require optimization but still have not been optimized are marked with a tilde (~) character before the function name. Though optimization may be delayed by the engine or skipped if the code is short-running, a tilde (~) points at a place where the code can be rewritten to achieve better performance.
    v8ProfilerCPUTrees.png

  • To navigate to the source code of a function, select the function in question in the tree and click edit on the toolbar or choose Jump to source on the context menu of the selection. The file with the source code of the selected function is opened in the editor with the cursor positioned at the function.
  • When a tab for a profiling session is opened, by default the nodes with heaviest calls are expanded. While exploring the trees, you may like to fold some nodes or expand other ones. To restore the original tree presentation, click the Expand Heavy Traces button icon_expand_heavy_calls.png on the toolbar.
  • To have IntelliJ IDEA display only the calls that indeed cause performance problems, filter out light calls:
    1. Click the Filter button filter on the toolbar.
    2. Using the slider, specify the minimum Total% or Parent% value for a call to be displayed and click Done.
  • To expand or collapse all the nodes in the active pane, click expandAll.png or collapseAll.png on the toolbar respectively.
  • To expand or collapse a node, select it and choose Expand Node or Collapse Node on the context menu of the selection.
  • Save and compare calls and lines:
    • To save a line with a function and its metrics, select the function and choose Copy on the context menu of the selection. This may be helpful if you want to compare the measurements for a function from two sessions, for example, after you make some improvements to the code.
    • To save only the function name and the name of the file where the function is defined, select the function and choose Copy Call on the context menu of the selection.
    • To compare an item with the contents of the Clipboard, select the item in question and choose Compare With Clipboard on the context menu of the selection. Compare the items in the Difference Viewer that opens.
  • To save the call tree in the current pane to a text file, click exportToTextFile.png on the toolbar and specify the target file in the dialog box that opens.

Analyzing the Timeline

Use the diagram in the Timeline tab to find where the application paused and explore the calls that provoked these pauses.

The Timeline tab is available only if you have installed the Gnuplot package as described above and specified the path to it in the run configuration.

  • To explore the processes within a certain period of time, select the fragment in question and click the Zoom button find.png on the toolbar or click the Zoom link on the selection.
    v8ProfilerCPUZoom1.png
    IntelliJ IDEA opens a new tab and shows the selected fragment enlarged to fit the tab width so you can examine the fragment with more details.
    v8ProfilerCPUZoom2.png
  • The longest pauses are marked with blue arrows arrowUp at the bottom of the diagram.
    v8ProfilerCPUShowStackFramesAt1.png
    To see the stack frame for a pause, click the arrow next to the moment in question. IntelliJ IDEA adds a new pane to the current tab, the name of the pane is Stack frames for <time period>, <pause duration> pause.
    v8ProfilerCPUShowStackFramesAt2.png
  • To resize the timeline chart to fit the screen of your device, click icon_image_size.png on the toolbar and choose the applicable image size.

Memory Profiling

Though the V8 Javascript engine does memory management for you, memory leaks or dynamic memory problems are still possible. Here are some examples of memory leaks or shortcomings reasons:

  • Using global objects to store collections of data, with complicated free policies.
  • Errors in usages of closures: closures keep references onto outside objects.
  • Keeping detached DOM nodes in javascript variables.
  • Too frequent memory allocation.
Memory management control is especially important for Node.js applications, because the server-side code tend to run long while memory inaccuracy is accumulated.

V8 heap snapshots are complicated by their nature; they include many “engine” objects; the inner structure of objects differs from what you expect while reading your code. Learn more at Javascript Memory Profiling.

Configuring Memory Profiling

To allow taking memory snapshots, you need to specify additional settings in the Node.js run configuration according to which the application will be launched.

  1. Choose Run | Edit Configuration on the main menu. Alternatively, click Shift+Alt+F10 and select Edit Configuration from the pop-up menu.
  2. From the list, choose the Node.js run configuration to activate CPU Profiling in or create a new configuration as described in Running and Debugging Node.Js.
  3. Switch to the V8 Profiling pane and specify the following:
    1. Select the Allow taling heap snapshots check box.
    2. In the Log folder field, specify the folder to store recorded logs in. Profiling data are stored in V8 log files isolate-<session number>.
    3. Specify the v8-profiler package to use. Choose the relevant package from the v8-profiler package drop-down list or click the browseButton button next to it and choose the package in the dialog box that opens.
    4. Specify the port through which IntelliJ IDEA communicates with the profiler, namely, sends a command to take a snapshot when you click the Take Heap Snapshot button ws_v8_profiling_take_snapshot on the toolbar of the Run tool window.

Collecting Memory Profiling Information

  1. Select the run configuration from the list on the main tool bar and then choose Run | Run <configuration name> on the main menu or click the Run toolbar button run.png.
  2. At any time during the application execution, click the Take Heap Snapshot button ws_v8_profiling_take_snapshot on the toolbar of the Run tool window.
  3. In the dialog box that opens, choose the folder to store the taken snapshot in and specify the name to save the snapshot file with. To start analyzing the snapshot immediately, select the Open snapshot check box.
  4. Click OK to save the snapshot.

Analyzing Memory Profiling Information

The collected profiling data is displayed in the V8 Heap Tool Window which opens when you take a snapshot at choose to open it. If the window is already opened and shows the profiling data for another session, a new tab is added. Tabs that were opened automatically are named after the run configurations that control execution of the applications and collecting the profiling data.

If you want to open and analyze some previously saved mempry profiling data, choose V8 Profiling - Analyze V8 Heap Snapshot on the main menu and select the relevant .snapshot file. IntelliJ IDEA creates a separate tab with the name of the selected file.

The tool window has three tabs that present the collected information from difference point of views.

  • The Containment tab shows the objects in you application grouped under several top-level entries: DOMWindow objects, Native browser objects, and GC Roots, which are roots the Garbage Collector actually uses. See Containment View for details.

    For each object, the tab shows its distance from the GC root, that is the shortest simple path of nodes between the object and the GC root, the shallow size of the object, and the retained size of the object. Besides the absolute values of the object's size, IntelliJ IDEA shows the percentage of memory the object occupies.

  • The Biggest Objects tab shows the most memory-consuming objects sorted by their retained sizes. In this tab, you can spot memory leaks provoked by accumulating data in some global object.
  • The Summary tab shows the objects in your application grouped by their types. The tab shows the number of objects of each type, their size, and the percentage of memory that they occupy. This information may be a clue to the memory state.

Each tab has a Details pane, which shows the path to the currently selected object from GC roots and the list of object’s retainers, that is, the objects that keep links to the selected object. Every heap snapshot has many “back” references and loops, so there are always many retainers for each object.

Navigating through a Snapshot

  • To help differentiate objects and move from one to another without losing the context, mark objects with text labels. To set a label to an object, select the object of interest and click ws_v8_profiling_mark.png on the toolbar or choose Mark on the context menu of the selection. Then type the label to mark the object with in the dialog box that opens.
  • To navigate to the function or variable that corresponds to an object, select the object of interest and click edit.png on the toolbar or choose Edit Source on the context menu of the selection. If the button and the menu option are disabled, this means that IntelliJ IDEA has not found a function or a variable that corresponds to the selected object.

    If several functions or variables are found, they are shown in a pop-up suggestion list.

  • To jump from an object in the Biggest Objects or Summary tab or Occurrences view to the same object in the Containment tab, select the object in question in the Biggest Objects or Summary tab and click ws_v8_profiling_navigate_in_main_tree.png on the toolbar or choose Navigate in Main Tree on the context menu of the selection. This helps you investigate the object from the containment point of view and concentrate on the links between objects.
  • To search through a snapshot:
    1. In the Containment tab, click find.png on the toolbar.
    2. In the V8 Heap Search Dialog that opens, specify the search pattern and the scope to search in. The available scopes are:
      • Everywhere: select this check box to search in all the scopes. When this check box is selected, all the other search types are disabled.
      • Link Names: select this check box to search among the object names that V8 creates when calling the C++ runtime, see http://stackoverflow.com/questions/11202824/what-is-in-javascript.

        In the V8 Heap Tool Window, link names are marked with the % character (%<link name>).

      • Class Names: select this check box to search among functions-constructors.
      • Text Strings: select this check box to perform a textual search in the contents of the objects.
      • Snapshot Object IDs: select this check box to search among the unique identifiers of objects. V8 assigns such a unique identifier in the format to each object when the object is created and preserves it until the object is destroyed. This means that you can find and compare the same objects in several snapshots taken within the same session.

        In the V8 Heap Tool Window, object IDs are marked with the @ character (@<object id>).

      • Marks: select this check box to search among the labels you set to objects manually by clicking ws_v8_profiling_mark.png on the toolbar of the Containment tab.

      The search results are displayed in the Details pane, in a separate Occurrences of '<search pattern>' view. To have the search results shown grouped by the search scopes you specified, press the Group by Type toggle button on the toolbar.

See Also

Last modified: 14 July 2015