IntelliJ IDEA Ultimate has out of the box support for profiling your applications using multiple Profilers. Now you can profile your application and analyze the results, without leaving your IDE. By profiling your application, you can discover the methods that execute in your application and for how long. Using these metrics, you can determine ways to improve the performance of your system.
In this blog post, I’ll walk you through the support that IntelliJ IDEA Ultimate has for profiling your applications. Let’s get started.
Profiler integrations in IntelliJ IDEA Ultimate
IntelliJ IDEA Ultimate has been supporting Profiler integration since its version 2018.3, with the Async Profiler.
IntelliJ IDEA Ultimate includes out of the box support for the Async and JFR profilers. These profilers can also be configured using settings (Preferences → Build, Execution, Deployment → Java Profiler):https://www.jetbrains.com/help/idea/async-profiler.html
JFR is built into the JVM. To use JFR, you’ll need to Configure your IntelliJ IDEA Ultimate to use a JDK distribution which includes JFR. Starting with Java 11, JFR is included on all JDK distributions. JFR works on Oracle JDK builds starting from version 8 (with its commercial features enabled). Work is in progress on merging JFR into OpenJDK8 tree. Moving forward, vendors are working on including JFR in the various versions of their JDK binaries. So, please check for the inclusion of JFR in the JDK binary you are using.
Support for JFR usage was introduced in IntelliJ IDEA Ultimate 2019.2. If you want to profile your applications using an older IntelliJ IDEA Ultimate version, you can use the Async profiler on Linux and macOS.
Run your application with a profiler
You can start profiling your application in multiple ways. Click on the start icon in the gutter and select ‘Run with ’. You can also choose this option from the ‘Run’ menu, or use Search Everywhere or Find Action to run ‘Run with Profiler’.
The output window displays a message stating ‘Profiler attached’, with a link to ‘Open’, to view the profiled data. Just in case, you miss the popup to view profiled data, you can open the Profiler window by using switcher or by using Find Action.
When you click on ‘Open’, you get an option to stop profiling and view the results:
Here’s capturing all these steps:
With the integrated profilers, you can view the Flame Graph, Call Tree, Method List or Events in IntelliJ IDEA Ultimate.
Working with Flame Graphs
Here’s a screenshot of a flame graph generated by profiling an application using Async CPU Profiler:
Every rectangle in a flame graph represents a function name. Blue rectangles represent native calls and yellow rectangles represent Java calls.
A flame graph is not a time series – it doesn’t show the sequence of calling of methods in an application. It shows which methods are calling other methods (this is how the method stacks are represented), for how long, and where they are executed. This graph might suggest where the problems are and where to optimize. A flame graph is another way of stating: hey, this is what happened when we profiled your application, and we grouped it. Note, the blocks are relative; it represents a snapshot total time on CPU.
A flame graph won’t disclose which tasks were performed or called before or after. It lets you find out the total CPU time that is being spent by your application. For example, if it spends 29% of the time on the methodA() method, that doesn’t mean it takes a lot of time to execute. It could also mean that you are calling it many times. So you could either think of reducing the number of calls to this method or optimize it so it executes in less time.
Flame graphs could be represented in a textual form, using Call Trees, showing how methods are called and the percentage of total CPU time used by them.
Call Tree shows the method execution path in your application. You could use them to get a quick overview of application activity, examine the execution path of slowest methods, determine critical execution paths and much more. Please refer to this link on our documentation page for more details on Call Tree.
Please also refer to our documentation on Profilers on our website.
As the name suggests, ‘Method Lists’ shows a list of methods that executed when you profiled your data, with the samples count.
When you profile your applications using the Java Flight Recorder, you can also view an Events tab. It enables you to view data related to JVM events like Class loading, Garbage collection, OS events and many more.
Attaching to an existing configuration
You can also attach the profiler to a process that is in execution (including the IDE). This essentially means that you don’t need to restart your application to profile it.
Select the option ‘Attach profiler to process..’ from the Run menu and then select from the list of processes that are executing.
Using Search method in the call tree
Application profiling can generate a lot of data. To quickly navigate to the metrics for a method you are looking for, you search it in the call tree using the search option in IntelliJ IDEA Ultimate. Transitioning to the flame graph is easy too. Right-click the method name and select ‘Focus on method name in flame graph’.
Search with filtering in call tree and viewing callees and backtraces
You could easily view callees and backtraces for methods in your profiled data with a single click:
Import profiling results created by other utilities
The profiled data can be stored in a file – by IntelliJ IDEA Ultimate and other utilities. You can import profiling results created by other utilities and IntelliJ IDEA:
Let me wrap up with what you can do with the integrated profilers in Java by sharing that you can also view ‘Method Merged Callees’ when you right-click a method name in flame graph or call list.
With out-of-the-box support for multiple profilers (Java Flight Recorder and Async Profiler), IntelliJ IDEA Ultimate makes it easier for you to profile your applications without leaving your IDE.
Happy Profiling with IntelliJ IDEA Ultimate.