Android Studio 3.0 replaces the Android Monitor tool with a new Android Profiler window. These new analytics tools provide real-time data on application CPU, memory, and network activity.

You can perform sample-based function tracing to record code execution times, collect heap dump data, view memory allocations, and view details of network transfer files.

How to use Android Profiler

Open the Android Profiler

To open the Android Profiler window, follow these steps:

  1. Click on theView > Tool Windows > Android Profiler(You can also click on the toolbarAndroid Profiler ).
  2. Select the device and application process you want to analyze from the Android Profiler toolbar. If you have a device connected via USB that is not listed in the device list, make sure you have USB debugging enabled. (If you are using an Android Emulator or a device with root permission, Android Profiler will list all running processes. Even though these processes may not be debugged. This process will be selected by default when you publish debugable applications.
  3. At the top of the Android Profiler window (shown below), select the device and application process that you want to analyze.

The Android Profiler shared timeline view should look like the following:

When you launch Android Profiler, it continues to collect analytics data until you disconnect the device or clickClose .

This shared timeline view shows only timeline charts. To use the detailed analysis tool, click on the chart that corresponds to the performance data you want to view. For example, to use tools to view heap data and track MEMORY allocations, click on the MEMORY diagram.

But not all analysis data is visible by default. If you see a message that says “Advanced profiling is unavailable for the selected process,” enable Advanced profiling in your run configuration.

Enabling advanced analysis

To display advanced analytics data, Android Studio must insert monitoring logic into your compiled application. Advanced analysis tools provide the following functions:

  • Event timeline (available in all analyzer Windows)
  • Allocate the number of objects (in Memory Profiler)
  • Garbage collection events (in Memory Profiler)
  • Details on all transferred files (in Network Profiler)

To enable advanced analysis, follow these steps:

  1. Select Run > Edit Configurations.
  2. Select your application module in the left pane.
  3. Click the Profiling TAB, then check Enable Advanced Profiling.

Now rebuild and run your application to get the full analysis capabilities. Note, however, that advanced analysis slows down your build speed, so enable this feature only if you want to start analyzing your application.

Note: Advanced profiling is not available for native code. If your application is a pure native application (without the Java Activity class), advanced profiling is not available. If your application uses JNI, you can use some of the advanced profiling features, such as Event timelines, GC Events, Java allocation objects, and Java-based network activities, but you cannot detect native allocation and network activities.

Check CPU activity and function tracing using CPU Profiler

CPU profilers help you examine your application’s CPU usage and thread activity in real time, and record function traces so you can optimize and debug your application code. Click anywhere in the CPU timeline in the Android Profiler window to open the CPU Profiler.

Why analyze CPU utilization

Minimizing an application’s CPU usage has many advantages, such as providing a faster, smoother user experience and extending device battery life. It also helps maintain good performance on a variety of old and new devices. When interacting with applications, you can use CPU profilers to monitor CPU utilization and thread activity. However, for detailed information on how an application executes its code, you should document and examine the function trace.

For each thread in the application process, you can see what functions were executed over a period of time and how much CPU each function consumed during its execution. You can also use function tracing to identify the caller and the called. A caller is a function that calls another function, and a callee is a function that is called by another function. You can use this information to determine which functions are responsible for calling tasks that often consume a lot of specific resources, and try to optimize your application code to avoid unnecessary work.

You should use Systrace if you want to collect detailed system-level data that helps you examine native system processes and eliminate frame-induced interface stutter.

Alternatively, if you want to export.trace files that you captured with the Debug class, you should use Traceview.

An overview of the CPU Profiler

When you turn on the CPU Profiler, it immediately starts showing the APPLICATION’s CPU usage and thread activity. The default view for a CPU Profiler looks like this:

As shown, the default view for a CPU Profiler includes the following:

  1. Event timeline: Shows the activities in an application that transition between different states of its life cycle and indicates user interactions with the device, including screen-rotation events. For more information about the Event timeline, including how to enable it, read Enabling Advanced Analysis.
  2. CPU timeline: Displays real-time APPLICATION CPU usage (expressed as a percentage of total available CPU time) and the total number of threads used by the application. This timeline also shows the CPU usage of other processes, such as system processes or other applications, so that you can compare it to your application usage. You can also examine historical CPU usage data by moving the mouse along the horizontal axis of the timeline.
  3. Thread activity timeline: Lists each thread belonging to the application process and marks their activity along the timeline using the colors listed below. After you record a function trace, you can select a thread from this timeline to examine its data in the trace pane.
  • Green: the thread is active or ready to use the CPU. That is, it is “running” or in the “runnable” state.
  • Yellow: indicates that the thread is active, but it is waiting for an I/O operation (such as disk or network I/O) before it can complete its work.
  • Gray: indicates that the thread is sleeping and is not consuming any CPU time. This occasionally happens when a thread needs to access a resource that is not yet available. The thread goes into self-sleep or the kernel puts the thread into sleep until the required resources are available.
  1. Logging configuration: Allows you to select one of the following options to determine how the analyzer logs function traces.
  • Sampled: A default configuration that captures the application call stack frequently during application execution. The analyzer compares the captured data sets to derive time and resource usage information related to application code execution. The inherent problem with “Sampled” based tracing is that if an application enters a function after capturing the call stack and exits the function before the next capture, the parser does not log the function call. If you are interested in such a tracing function with a short lifetime, you should use “Instrumented” tracing.
  • Instrumented: A default configuration that sets the application at run time to log timestamps at the start and end of each function call. It collects timestamps and compares them to generate function tracking data, including time information and CPU utilization. Note that the overhead associated with setting up each function affects runtime performance and may affect analysis data, especially for functions with relatively short life cycles. In addition, if an application executes a large number of functions in a short period of time, the analyzer can quickly exceed its file size limit and cannot record any more trace data.
  • Edit Configurations: Allows you to change some of the default values of the “Sampled” and “Instrumented” record configurations above and save them as custom configurations. For more information, go to the Create Record Configuration section.
  1. Record button: Used to start and stop recording function tracing. For more information, go to the Logging and checking function trace section.

Note: The profiler also reports Android Studio and Android platforms added to your application processes such as JDWP, Profile Saver, Studio:VMStats, Studio:Perfa, and Studio:Heartbeat, Although the exact names shown in the thread activity timeline may vary) thread CPU utilization. This means that the CPU usage applied in the CPU timeline also reflects the CPU time used by these threads. You can view some of these threads in the thread activity timeline and monitor their activity. (However, because parser threads execute native code, you cannot record function trace data for them.) Android Studio reports this data so that you can easily identify when thread activity and CPU utilization are actually triggered by application code.

Record and check function traces

To begin recording function tracing, select from the drop down menuSampledInstrumentedRecord the configuration, or select the one you createdCustom record configurationAnd then clickRecord . Interact with the application and click when doneStop recording . The analyzer automatically selects the time range for the record and displays its trace information in the function trace pane. If you want to check the function trace for another thread, simply select it from the thread activity timeline. Record the CPU Profiler view after the function trace, as shown below:

  1. Select time range: Used to determine which part of the recorded time range you want to examine in the trace pane. When you first record a function trace, the CPU Profiler will automatically select the full length of your record in the CPU timeline. If you want to examine function trace data for only a small part of the recorded time range, you can click and drag the edge of the highlighted area to modify its length.
  2. Timestamps: Used to indicate the start and end times of the recorded function trace (relative to when the analyzer started collecting CPU usage information from the device). When selecting a time range, you can click the timestamp to automatically select the full record, which is especially useful if you have multiple records to switch between.
  3. Trace pane: Function trace data for displaying the time range and thread of your choice. This pane is displayed only if you record at least one function trace. In this pane, you can choose how you want to view each stack trace (using the trace TAB) and how to measure the execution time (using the time reference drop-down menu).
  4. Once selected, you can display your function trace in the form of a Top Down tree, Bottom Up tree, call chart, or flame chart. You can learn more about each trace pane label below.
  5. Select one of the following options from the drop-down menu to determine how to measure the time information for each function call:
  • Wall clock time indicates the actual elapsed time.
  • Thread Time: The Thread time information represents the actual elapsed time minus any amount of time that the Thread did not consume CPU resources. For any given function, the thread time is always less than or equal to its wall clock time. Using thread time gives you a better idea of how much of the actual CPU usage of a thread is consumed by a given function.

Use Memory Profiler to view Java heap and Memory allocation

The Memory Profiler is a component in the Android Profiler that helps you identify Memory leaks and drains that cause your application to stall, freeze, and even crash. It displays a real-time chart of application memory usage, allowing you to capture heap dumps, enforce garbage collection, and track memory allocation. To open the MEMORY Profiler, click anywhere in the MEMORY timeline in the Android Profiler window. Alternatively, you can use Dumpsys on the command line to check your application memory and see GC events in logcat.

Why should your application memory be analyzed

Android provides a managed memory environment – when it determines that your application no longer uses objects, the garbage collector releases unused memory back into the heap. While the way Android finds unused memory continues to improve, with all versions of Android, the system must briefly pause your code at some point. Most of the time, these pauses are hard to detect. However, if your application allocates memory faster than the system can reclaim it, your application may be delayed when the collector frees enough memory to meet your allocation needs. This delay can cause your application to skip frames and slow down the system significantly.

Although your application will not appear to be slowing down, if there is a memory leak, it will retain that memory even if the application is running in the background. This behavior forces unnecessary garbage collection events, thus slowing down the system’s memory performance. Finally, the system is forced to terminate your application process to reclaim memory. Then, when the user returns to your application, it must be completely restarted.

To help prevent these problems, you should use the Memory Profiler to do the following:

  • Look for less-than-ideal memory allocation patterns in the timeline that could cause performance problems.
  • Dump the Java heap to see which objects are running out of usable memory at any given time. Multiple heap dumps over time can help identify memory leaks.
  • Record memory allocation during normal and extreme user interactions to identify exactly where your code is allocating too many objects in a short time, or is allocating leaking objects.

To learn about programming practices that can reduce application memory usage, read Managing Your Application Memory.

An overview of the Memory Profiler

When you first open the Memory Profiler, you see a detailed timeline of the amount of Memory used by your application and access various tools for enforcing garbage collection, capturing heap dumps, and recording Memory allocation. The default view of a Memory Profiler looks like this:

As shown in the figure, the default view of the Memory Profiler includes the following:

  1. A button to enforce a garbage collection Event.
  2. Button to capture heap dumps.
  3. Button used to record memory allocation. This button will only be displayed when connected to a device running Android 7.1 or lower.
  4. Buttons to zoom in/out of the timeline.
  5. Button to jump to live memory data.
  6. Event timeline, which shows activity status, user input events, and screen rotation events.
  7. Memory usage timeline, which contains the following:
  • A stacked chart showing how much memory is used by each memory category, as shown on the Y-axis on the left and the color keys at the top.
  • The dotted line represents the number of objects allocated, as shown on the Y-axis on the right.
  • An icon used to represent each garbage collection Event.

However, if you are using a device running Android 7.1 or lower, not all of the analysis data is visible by default. If you see a message that says “Advanced profiling is unavailable for the selected process,” you need to enable Advanced profiling to view the following:

  • The Event time line
  • Number of allocated objects
  • Garbage Collection Event

On Android 8.0 and later, always enable advanced analytics for debugable applications.

How to calculate memory

The number you see at the top of the Memory Profiler depends on how many private Memory pages your application commits according to the Android system mechanism. This count does not include pages shared with the system or other applications. The Memory count legend at the top of the Memory Profiler looks like this:

The categories in the memory count are as follows:

  • Java: Object memory allocated from Java or Kotlin code.
  • Native: Object memory allocated from C or C++ code.

Even if you don’t use C++ in your application, you might see some of the native memory used here, because the Android framework uses native memory to represent you for tasks such as image resources and other graphics, even if you write code in Java or Kotlin.

  • The buffer queue displays the memory used by pixels (including GL surfaces, GL textures, and so on) to the screen. (Please note that this is CPU-shared memory, not GPU-dedicated memory.)
  • Stack: The memory used by the native Stack and Java Stack in your application. This usually depends on how many threads your application runs.
  • Code: The memory your application uses to process Code and resources such as dex bytecodes, optimized or compiled dex codes,.so libraries, and fonts.
  • Other: Memory used by your application that the system is not sure how to classify.
  • Allocated: Number of Java/Kotlin objects Allocated to your app. It doesn’t count toward objects allocated in C or C++.

When connecting to devices running Android 7.1 and below, this allocation only starts counting when the Memory Profiler connects to your running application. Therefore, any objects allocated before you start the analysis will not be counted. However, Android 8.0 comes with a built-in device analysis tool that keeps track of all allocations, so on Android 8.0 and later, this number always represents the total number of Java objects to be processed in your application.

The new Memory Profiler records your Memory differently than the Memory counts in the previous Android Monitor tools, so your Memory usage may now look higher. The Memory Profiler monitors more categories, which increases the total Memory usage, but if you only care about The Java heap Memory, the number of “Java” entries should be similar to the number in the previous tool.

However, the Java number may not be exactly the same as the number you see in Android Monitor, because the application’s Java heap is started from Zygote, and the new number counts toward all the physical memory pages assigned to it. Therefore, it can accurately reflect how much physical memory your application is actually using.

Note: Currently, the Memory Profiler also displays the native Memory usage of some false positives in the application, which is actually used by the analysis tool. For approximately 100,000 objects, this increases the reported memory usage by up to 10MB. In future versions of these tools, these numbers will be filtered out of your data.

Viewing Memory Allocation

Memory allocation shows how each object in memory is allocated. Specifically, the Memory Profiler can show you the following information about object allocation:

  • What types of objects are allocated and how much space they use.
  • The stack trace for each assignment, which thread is included.
  • When objects are unallocated (only when using devices running Android 8.0 or later).

If your device is running Android 8.0 or higher, you can view your object allocation at any time by simply clicking and holding down the timeline and dragging to select the area you want to view the allocation. There is no need to start recording sessions, as Android 8.0 and later ship with built-in analytics tools to keep track of your app allocations. As follows:

If your device is running Android 7.1 or lower, click in the Memory Profiler toolbarRecord memory allocations . As you record, Android Monitor keeps track of all assignments that are made in your application. When the operation is complete, clickStop recording (Same button) to view assignments. As follows:

After selecting a timeline area (or when you complete recording sessions using a device running Android 7.1 or lower), the list of allocated objects is displayed under the timeline, grouped by class name, and sorted by their heap count.

Note: On Android 7.1 and later, you can record up to 65535 assignments. If your recording session exceeds this limit, only the last 65535 allocations are saved in the record. (In Android 8.0 and later, there are no actual restrictions.)

To check the allocation record, follow these steps:

  1. Browse the list for objects with abnormally large heap counts and possible leaks. To help find known classes, click the Class Name column header to sort alphabetically. Then click on a class name. The Instance View pane appears on the right, showing each Instance of the class, as shown in the figure below.
  2. In the Instance View pane, click on an Instance. The Call Stack TAB appears below, showing where and in which thread the instance is assigned.
  3. inCall StackTAB, click any line to jump to the code in the editor. Details about each allocated object are displayed in the Instance View on the right, as shown below:

By default, the assignment list on the left is arranged by class name. At the top of the list, you can use the drop-down list on the right to toggle between the following arrangements:

  • Arrange by class: Groups all assignments based on class names.
  • Arrange by Package: Groups all assignments based on software package names.
  • Arrange by callstack: groups all assignments into their corresponding callstack.

Capture heap dump

Heap dumps show which objects in your application were using memory at the time you captured the heap dump. Especially after a long user session, the heap dump helps identify memory leaks by showing objects that are still in memory that you thought should no longer be there. After you capture the heap dump, you can view the following information:

  • What types of objects have been assigned to your application, and how many for each type.
  • How much memory each object is using.
  • Where in the code each object is still referenced.
  • The call stack to which objects are allocated. (Currently, if you capture a heap dump while recording an allocation, the heap dump can only use the call stack in Android 7.1 and later.)

To capture a heap dump, click in the Memory Profiler toolbarDump Java heap . During the dump heap, the amount of Java memory may increase temporarily. This is normal because the heap dump happens in the same process as your application and requires some memory to collect the data.

The heap dump is displayed under the memory time line, showing all the class types in the heap, as shown below:

Note: If you need to be more precise about when the dump was created, you can create a heap dump ata key point in your application code by calling dumpHprofData().

To check your heap, follow these steps:

  1. Browse the list for objects with abnormally large heap counts and possible leaks. To help find known classes, click the Class Name column header to sort alphabetically. Then click on a class name. The Instance View pane appears on the right, showing each Instance of the class, as shown in the figure below.
  2. In the Instance View pane, click on an Instance. References appear below, showing each reference to this object. Alternatively, click the arrow next to the instance name to see all of its fields, and then click a field name to see all of its references. If you want to see Instance details of a field, right-click the field and select Go to Instance.
  3. In the References TAB, if you find a reference that might be leaking memory, right-click it and select Go to Instance. This will select the corresponding instance from the heap dump and display your own instance data.

By default, the heap dump does not show you a stack trace for each allocated object. To get stack tracing, you must first start recording memory allocation before clicking Dump Java Heap. You can then select an Instance in the Instance View and View the Call Stack TAB as well as the References TAB, as shown below. However, some objects may have been allocated before you started recording allocations, so the call stack cannot be used for these objects. Instances that contain the call stack are represented by a “stack” flag on the icon. (Unfortunately, because stack tracing requires you to perform allocation records, you cannot currently view stack tracing for heap dumps on Android 8.0.)

By default, the heap dump does not show you a stack trace for each allocated object. To get stack tracing, you must first start recording memory allocation before clicking Dump Java Heap. You can then select an Instance in the Instance View and View the Call Stack TAB as well as the References TAB, as shown below. However, some objects may have been allocated before you started recording allocations, so the call stack cannot be used for these objects. Contains the instance of the call stack in the iconIs represented by a “stack” flag. (Unfortunately, because stack tracing requires you to perform allocation records, you cannot currently view stack tracing for heap dumps on Android 8.0.)

In your heap dump, be aware of memory leaks caused by any of the following:

  • Long references to activities, Context, views, Drawable, and other objects may keep references to the Activity or Context container.
  • You can keep the Activity instance’s non-static inner class, such as Runnable.
  • The cache where the object is held longer than required.

The duration required to capture a heap dump is indicated in the timeline, as shown below:

In the class list, you can view the following information:

  • Heap Count: the number of instances in the Heap.
  • Shallow Size: The total Size, in bytes, of all instances in the heap.
  • Retained Size: The total Size (in bytes) of memory Retained for all instances of this type.

At the top of the class list, you can use the left drop-down list to switch between the following heap dumps:

  • Default heap: when the system does not specify a heap.
  • App Heap: The main heap to which your application allocates memory.
  • Image Heap: A system boot Image that contains classes preloaded during boot. The allocation here is guaranteed never to move or disappear.
  • Zygote Heap: copy-on-write heap in which application processes are derived from the Android system.

By default, the list of objects in this heap is arranged by class name. You can use other drop-down lists to toggle between the following arrangements:

  • Arrange by class: Groups all assignments based on class names.
  • Arrange by Package: Groups all assignments based on software package names.
  • Arrange by callstack: groups all assignments into their corresponding callstack. This option is only available if a heap dump is captured during record allocation. Even so, objects in the heap are likely allocated before you start recording, so these allocations are shown first and listed only by class name.

By default, this list is ordered by Retained Size column. You can click on any column header to change how the list is sorted.

In Instance View, each Instance contains the following information:

  • Depth: The shortest number of hops from any GC root to the selected instance.
  • Shallow Size: The Size of this instance.
  • Retained Size: The Size of memory controlled by this instance (based on the Dominator tree).

Save the heap dump as HPROF

After the heap dump is captured, the data can only be viewed in the Memory Profiler while the analyzer is running. When you exit the analysis session, you lose the heap dump. Therefore, if you want to save the heap dump for later review, click on the toolbar below the time lineExport heap dump as HPROF file , export the heap dump to a HPROF file. In the dialog box that displays, make sure to use.hprofSuffixes save files.

You can then reopen the file in Android Studio by dragging it to an empty editor window (or dragging it to the file TAB bar).

To use other HPROF profilers, such as JHAT, you need to convert the HPROF file from the Android format to the Java SE HPROF format. You can do this using the hprof-conv tool provided in the android_sdk/platform-tools/ directory. Run the hprof-conv command with two parameters: the original hprof file and the location where the converted hprof file was written. Such as:

hprof-conv heap-original.hprof heap-converted.hprof
Copy the code

Techniques for analyzing memory

With Memory profilers, you should apply pressure to your application code and try to force Memory leaks. One way to cause a memory leak in an application is to let it run for a while and then check the heap. Leaks in the heap may gradually converge to the top of the allocation. However, the smaller the leak, the longer you need to run the application to see the leak.

You can also trigger a memory leak in one of the following ways:

  • Rotate the device from portrait to landscape, and then do this multiple times in different Activity states. Rotating the device often causes the application to leak the Activity, Context, or View object because the system recreates the Activity, and if your application keeps referring to one of these objects elsewhere, the system cannot garbage collect it.
  • When in different Activity states, switch between your app and another app (navigate to the home screen, then return to your app).

Tip: You can also perform the above steps using the MonkeyRunner testing framework.

Check Network traffic using Network Profiler

Network profilers are capable of displaying real-time Network activity on a timeline, including data sent and received and the current number of connections. This allows you to see how and when your application transfers data and optimize the underlying code accordingly. To open NETWORK Profiler, click anywhere in the NETWORK timeline in the Android Profiler window.

Why should application network activity be analyzed

When your application makes a request to the network, the device must use a high-power mobile or WLAN wireless device to send and receive packets. Not only do wireless devices consume power to transmit data, they also consume extra power to turn on and not lock the screen.

With Network Profiler, you can look for frequent, short-term spikes in Network activity, meaning that your application needs to turn on the wireless device frequently or leave the screen unlocked for long periods of time to handle a large number of short-term requests in a cluster. This mode means you can optimize applications and improve battery life by batching network requests and reducing the number of times you have to turn on your wireless device to send or receive data. This approach also allows wireless devices to adjust to a low-power mode, extending the time between batch processing requests and saving energy.

For more tips on optimizing application network activity, see Reducing Network Power Consumption.

The Network Profiler overview

The default view of a Network Profiler looks like this:

Note: Advanced analysis must be enabled to select a fragment from the timeline to examine, view a list of files sent and received, or view details about selected files sent or received. To enable advanced analysis, see Enabling Advanced Analysis.

Check the network connection

If the Network Profiler detects traffic values but is unable to identify any supported Network requests, you receive the following error message:

Network Profiling Data Unavailable: There is no information for the network traffic you’ve selected.”

Network Profiler currently supports only the HttpURLConnection and OkHttp Network connection libraries. If your application uses other Network connection libraries, you may not be able to view Network activity in the Network Profiler. If you receive this error message but your application does use HttpURLConnection or OkHttp, please report the error or search the Issue Tracker to add your feedback to existing reports related to your problem. In addition, you can provide support for other libraries with the following resource requests.

Thank you

Measure application performance using Android Profiler

Measure app performance with Android Profiler