Memory usage (anonymous RSS + swap)

Memory usage (anonymous RSS + swap) is a metric in Android vitals that reflects your app's memory usage.

Anonymous memory is memory not backed by a file on storage, such as heap allocations and mmap-allocated memory. This captures your app's dynamic memory allocations, including the Java or Kotlin heap, unmanaged native heap allocations (where Bitmap pixel data lives on Android 8.0 (API level 26) and higher), and thread execution stacks. While the OS can drop file-backed memory under pressure, it can't drop anonymous memory.

Resident Set Size (RSS) is the total number of memory pages (both shared and non-shared) used by a process that are held in physical RAM. A page is considered "shared" if it's accessed by more than one process (such as apps that access the same library).

For anonymous memory, the system can write pages to swap space (or zRAM on Android) when memory is under pressure. The system can read these pages back from swap if needed.

Altogether, memory usage (anonymous RSS + swap) is a measure of your app's total number of memory pages not backed by a file on storage, inclusive of any memory that's also being preserved by the system in swap. Tracking anonymous RSS + swap ensures you see your app's true, unevictable memory footprint.

If your app's memory usage is high, investigate further and fix the problem using the guidance on this page.

Identify high memory usage

Android vitals

Android vitals shares your app's memory usage broken down by the following process states:

  • Foreground: The app's process is visible. High P99 here often affects user-perceived performance (jank or OOM crashes) and is heavily driven by unevicted UI components or activities.
  • Foreground Service: The app is running a foreground service. Because these services are designed for long-running tasks, they're prime candidates for cumulative lifecycle leaks that aggressively inflate the P99 tail over time.
  • Background: The app is running a background service, or recently backgrounded, but not yet cached. This is where background processing leaks compound.
  • Cached: The app is in a cached state. This state is highly sensitive to system memory pressure such as LMKs. Because the OS can evict this process state at will, this state is provided only for debug purposes.

To understand how these process states correlate with onTrimMemory callbacks, consult the guidance on releasing memory in response to events.

Android vitals also breaks down your app's memory usage by RAM buckets. The memory usage metric is displayed as a timeline of daily percentile values, alongside the most recent daily value for the 50th and 90th percentiles.

Once you have identified your memory baseline, follow the guidance to diagnose and improve excessive memory usage.

Identify memory leaks using tail skew

To help identify memory leaks, look for a divergence between your typical (P50) and tail-end (P90) users in Android vitals. While general asset bloat inflates memory uniformly across all percentiles, memory leaks compound over time, heavily skewing the tail-end data.

You should compare your P90 and P99 metrics against your P50 baseline by process name. If your P90 to P50 ratio exceeds 3.5x, it indicates a likely memory leak during extended sessions. For certain use cases, an elevated ratio doesn't always indicate a leak, but you should evaluate the specific workflow to determine if the elevated memory usage is expected behavior.

Resources

Diagnose excessive memory usage locally

To get started with diagnosing the source of excessive memory usage, you can capture a heap dump with Record heap dump in developer settings, Android Studio, or Perfetto. We recommend you start by capturing a heap dump locally after testing your app's core user journeys.

We especially recommend testing the following user journeys:

  • Webviews and In-App Browser Sessions
  • Media-heavy infinite scrolling
  • Asset creation and editing flows

To investigate potential memory leaks, first identify the highest-consuming processes using the Process name table in the Android vitals memory usage dashboard. Next, run the corresponding user journeys locally and collect heap dumps across different process states (visible, foreground service, and cached) to verify if the app releases memory after being backgrounded.

If you're debugging memory issues using the Android Studio Profiler, you can also use the LeakCanary integration to streamline leak detection and duplicate bitmap detection to optimize your image usage.

After you've collected the heap dump, we recommend using the Perfetto AI Skills to analyze the heap dump and identify potential sources of high memory usage.

Here's an example of what the AI skills could respond with:

I have completed the analysis of memory leaks and bitmap issues for [app] using the provided Perfetto trace.
  Summary of Findings
  The investigation identified a critical memory pressure issue caused by massive bitmap retention within the app process.
...
Recommendations for [app]
   1. [Library] Image Cache Optimization:
       * Review the [Library] caching strategy. Ensure that bitmaps
         loaded for animations are released or downsampled when the animation is
         not in the foreground.
   2. Asset Resolution Audit:
       * The 14.7 MB average size suggests full-screen or extremely high-density assets. Audit the [library] files in the native_home component to ensure they are not using unnecessarily large source images.
   3. View Lifecycle Management:
       * Investigate why 21 [LibraryImage] instances are alive simultaneously. Ensure that views in the bottom
      tab are properly detached or their animations are cleared when switching between tabs.
   4. Fix Surface Leaks:
       * Address the Surface.release failures observed in the logs, as these can lead to both memory leaks and
         native resource exhaustion.

Additional resources for interpreting heap dumps

The following resources provide more information about interpreting heap dumps and debugging memory usage:

Improve memory usage

Consult these sections to learn more about improving your app's memory usage:

For detailed guidance on fixing memory issues, consult the Manage your app's memory guide.