Android Memory Panorama Analysis Guide

July 23, 2026 · View on GitHub

Overview

Panorama Analysis is the core feature of this toolkit, providing deep insights into Android application memory usage by correlating multiple data sources. Its quantitative entry point is the familiar dumpsys meminfo row order; smaps supplements each comparable row rather than replacing the Android summary with a separate TOP list. Panorama analysis can:

  1. Reconcile meminfo and smaps row by row: Preserve every meminfo field and attach comparable smaps PSS/SwapPss and mapping evidence
  2. Correlate Java and Native memory: e.g., link Java Bitmap objects to their Native pixel memory
  3. Track Native memory allocations: Distinguish between tracked and untracked Native memory
  4. Integrate GPU/Graphics memory: Including GraphicBuffer and GPU cache
  5. System memory context: Analyze system memory pressure and Swap/zRAM usage
  6. DMA-BUF analysis: Track hardware buffer memory for GPU, Camera, Display, etc.
  7. Detect potential issues: Automatically discover memory anomalies and provide optimization suggestions
  8. Threshold alerts: Support custom thresholds for CI/CD integration

Data Sources

Panorama analysis integrates the following data sources:

Data SourceCommandKey InformationRequired
meminfodumpsys meminfo <pkg>Memory summary, Native Allocations (precise Bitmap stats)Recommended
gfxinfodumpsys gfxinfo <pkg>GPU cache, GraphicBuffer, frame statsRecommended
hprofam dumpheap <pkg> <path>Java heap objects, reference chainsOptional
smapscat /proc/<pid>/smapsDetailed memory mapping (requires Root)Optional
proc_meminfocat /proc/meminfoSystem memory status, memory pressureOptional
dmabufcat /sys/kernel/debug/dma_buf/bufinfoDMA-BUF hardware buffers (requires Root)Optional
zram_swap/proc/swaps + /sys/block/zram*/mm_statzRAM compression, Swap usageOptional

Key Discovery: Native Allocations

The Native Allocations section in dumpsys meminfo provides precise Bitmap statistics:

Native Allocations
   Bitmap (malloced):       27                           6939
   Bitmap (nonmalloced):     8                          11873

This is the key bridge for correlating Java Bitmap objects with Native memory!

  • malloced: Bitmap pixel memory allocated via malloc
  • nonmalloced: Directly allocated Bitmap pixel memory (e.g., ashmem)

Usage

One-Click Dump and Analysis

# List running applications
python3 analyze.py live --list

# Full analysis (including hprof)
python3 analyze.py live --package com.example.app

# Quick analysis (skip time-consuming hprof)
python3 analyze.py live --package com.example.app --skip-hprof

# Dump only, no analysis
python3 analyze.py live --package com.example.app --dump-only -o ./dumps

One-click dump automatically collects:

  • meminfo.txt - dumpsys meminfo output
  • gfxinfo.txt - dumpsys gfxinfo output
  • smaps.txt - /proc/pid/smaps (requires Root)
  • proc_meminfo.txt - /proc/meminfo system memory
  • zram_swap.txt - zRAM/Swap information
  • heap.hprof - Java heap snapshot (can be skipped)

Analyze Existing Data

# Analyze dump directory (auto-reads all files)
python3 analyze.py panorama -d ./dumps/com.example.app_20231225_120000

# Analyze individual files
python3 analyze.py panorama -m meminfo.txt -g gfxinfo.txt

# Full analysis (including all data sources)
python3 analyze.py panorama -m meminfo.txt -g gfxinfo.txt -H app.hprof -S smaps.txt \
    -P proc_meminfo.txt -D dmabuf_debug.txt -Z zram_swap.txt

Output Formats

# Default terminal output
python3 analyze.py panorama -d ./dump

# JSON output (for automation)
python3 analyze.py panorama -d ./dump --json -o result.json

# Markdown report
python3 analyze.py panorama -d ./dump --markdown -o report.md

Threshold Alerts (CI/CD Integration)

# Set memory thresholds
python3 tools/panorama_analyzer.py -d ./dump \
    --threshold-pss 300 \
    --threshold-java-heap 100 \
    --threshold-native-heap 80 \
    --threshold-views 500

# Exit code: 0=OK, 1=WARNING, 2=ERROR

Available threshold parameters:

ParameterDescriptionUnit
--threshold-pssTotal PSS thresholdMB
--threshold-java-heapJava Heap thresholdMB
--threshold-native-heapNative Heap thresholdMB
--threshold-graphicsGraphics thresholdMB
--threshold-native-untrackedNative untracked ratio threshold%
--threshold-jankyJank rate threshold%
--threshold-viewsView count thresholdcount
--threshold-activitiesActivity count thresholdcount
--threshold-bitmapsBitmap count thresholdcount
--threshold-bitmap-sizeBitmap total size thresholdMB

Report Interpretation

meminfo Primary Ledger + smaps Row Evidence

When both sources are available, the report starts with every main-table meminfo row in source order. Native Heap, Dalvik Heap, mappings, stacks, devices, Unknown, and TOTAL remain recognizable, while comparable smaps PSS/SwapPss and mapping details appear alongside them.

EGL mtrack, GL mtrack, and other driver/HAL rows are labelled not-comparable; absence from /proc/<pid>/smaps is expected. The total reconciliation uses the explicit formula smaps_total_pss_kb + meminfo_memtrack_only_pss_kb and reports the residual delta. HPROF retained bytes, system DMA-BUF totals, and other accounting domains are not added to that formula.

Dalvik Details follow the main table as drill-down rows and do not form another process total.

Memory Overview

────────────────────────────────────────
[ Memory Overview ]
────────────────────────────────────────
Total PSS:                   142.08 MB
Java Heap:                   31.85 MB
Native Heap:                 44.76 MB
Graphics:                    29.27 MB
Code:                        15.29 MB
Stack:                        1.11 MB
MetricDescriptionFocus Points
Total PSSActual physical memory occupied by processOverall memory usage
Java HeapDalvik/ART heap memoryJava objects, leak detection
Native HeapC/C++ heap memoryNative code, JNI
GraphicsGraphics-related memoryBitmap, GPU resources
CodeCode segment memoryDEX, SO libraries
StackThread stack memoryThread count

System Memory Context

────────────────────────────────────────
[ System Memory Context ]
────────────────────────────────────────
System Total: 3579 MB (3.50 GB)
Available:    2099 MB (58.6%)
Pressure:     🟢 LOW
Swap Usage:   256 / 2048 MB (12.5%)
ION Memory:   169 MB
MetricDescriptionFocus Points
System TotalDevice physical memory totalDevice specifications
AvailableMemory available for allocation<20% needs attention
PressureLOW/MEDIUM/HIGH/CRITICALHIGH+ affects performance
Swap UsagezRAM/Swap usageHigh usage indicates memory pressure
ION MemoryGPU/Camera hardware memoryRelated to Graphics

zRAM/Swap Analysis

────────────────────────────────────────
[ zRAM/Swap Analysis ]
────────────────────────────────────────
Swap Total:       2048.0 MB (1 device)
Swap Used:         512.0 MB (25.0%)
zRAM Disk:        2048.0 MB (1 device)
Original Data:    1200.0 MB
Compressed Data:   280.5 MB
Actual Mem Used:   300.2 MB
Compression Ratio:   4.28x
Space Saved:        76.6%
Memory Saved:      899.8 MB
MetricDescriptionFocus Points
Swap UsageSwap space used ratio>50% needs attention, >80% memory pressure
Compression RatioOriginal/Compressed>2x is normal, <1.5x data not very compressible
Memory SavedActual memory saved by compressionzRAM effectiveness

DMA-BUF Analysis

────────────────────────────────────────
[ DMA-BUF Analysis ]
────────────────────────────────────────
Total DMA-BUF: 156.7 MB (89 buffers)
  GPU Graphics:   120.45 MB (56 buffers)
  Display:         24.00 MB (12 buffers)
  Camera:           8.25 MB (15 buffers)
  Video:            4.00 MB (6 buffers)

DMA-BUF is a Linux kernel mechanism for cross-device memory sharing, used in Android for:

  • GPU: Textures, render buffers
  • Display: SurfaceFlinger composition buffers
  • Camera: Camera preview and capture buffers
  • Video: Video decode/encode buffers

Bitmap Deep Analysis

────────────────────────────────────────
[ Bitmap Deep Analysis ]
────────────────────────────────────────
Bitmap Total: 35 objects (18.37 MB)
  - malloced (Java managed): 27 / 6.78 MB
  - nonmalloced (Native):     8 / 11.59 MB
GPU Cache: 15.34 MB
GraphicBuffer: 12 / 12.45 MB

Bitmap Types

  1. malloced Bitmap

    • Pixel memory allocated via malloc()
    • Counted in Native Heap
    • Can be freed via Bitmap.recycle()
  2. nonmalloced Bitmap

    • Directly allocated via ashmem or other mechanisms
    • Not counted in Native Heap
    • Usually hardware-accelerated Bitmaps

Graphics Memory

  1. GPU Cache

    • GPU shader cache
    • Texture cache
    • Font cache
  2. GraphicBuffer

    • Surface-related graphics buffers
    • Video/camera preview buffers
    • Hardware-accelerated rendering buffers

Native Memory Tracking

────────────────────────────────────────
[ Native Memory Tracking ]
────────────────────────────────────────
Native Heap PSS: 44.76 MB
  - Tracked: 39.00 MB (87.1%)
    - Bitmap: 18.37 MB
    - Other malloced: 15.43 MB
    - Other nonmalloced: 5.20 MB
  - Untracked: 5.76 MB (12.9%)

Tracked Native Memory

Includes:

  • Bitmap (malloced + nonmalloced)
  • Other malloced allocations
  • Other nonmalloced allocations

This memory can be seen in the Native Allocations section of dumpsys meminfo.

Untracked Native Memory

Formula: Untracked = Native Heap - Tracked portion

Possible sources:

  • Third-party Native libraries
  • Direct allocations in JNI code
  • System library allocations
  • Memory leaks

Important Warning: If untracked Native memory is too high (>30%), it needs attention!

UI Resource Statistics

────────────────────────────────────────
[ UI Resources ]
────────────────────────────────────────
Views: 863 | Activities: 1 | ViewRootImpl: 6 | WebViews: 0
MetricNormal RangeAbnormal
Views<5000Too many may cause UI lag
ViewRootImpl1-3>5 may indicate window leak
Activities1-5>10 may indicate Activity leak
WebViews0-2Each WebView consumes significant memory

Frame Statistics

────────────────────────────────────────
[ Frame Statistics ]
────────────────────────────────────────
Jank Rate: 12.5%
Frame Latency: p50=8ms | p90=16ms
MetricGoodNeeds Optimization
Jank frames<10%>20%
P50<10ms>16ms
P90<16ms>32ms

Anomaly Detection

Panorama analysis automatically detects the following anomalies:

1. Native Memory Anomaly

[!!] UNTRACKED_NATIVE: 44.8 MB untracked Native memory
    -> Use malloc_debug or ASan to detect Native memory allocations

2. UI Resource Anomaly

[!] TOO_MANY_VIEWS: View count 863 is high
    -> Consider using RecyclerView, ViewStub or simplifying layouts

3. Frame Rate Anomaly

[!] HIGH_JANK: Jank rate 39.9% is high
    -> Use Perfetto or Systrace to analyze jank causes

Diff Analysis

Panorama analysis also supports comparing two dumps to find memory growth issues:

# Compare two dump directories
python3 analyze.py diff -b ./dump_before -a ./dump_after

# Or compare individual meminfo files
python3 analyze.py diff --before-meminfo m1.txt --after-meminfo m2.txt

Diff analysis shows:

  • Memory changes by category
  • View/Activity count changes
  • Frame rate changes
  • Highlighted items exceeding thresholds

Optimization Recommendations

Bitmap Optimization

  1. Recycle unused Bitmaps promptly

    if (bitmap != null && !bitmap.isRecycled()) {
        bitmap.recycle();
        bitmap = null;
    }
    
  2. Use appropriate Bitmap configuration

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 2;  // Scale down
    options.inPreferredConfig = Bitmap.Config.RGB_565;  // Reduce memory
    
  3. Use image loading library's memory management

    Glide.with(context)
        .load(url)
        .override(targetWidth, targetHeight)
        .format(DecodeFormat.PREFER_RGB_565)
        .into(imageView);
    

Native Memory Optimization

  1. Review memory allocations in JNI code
  2. Use AddressSanitizer to detect leaks
  3. Audit third-party Native libraries

UI Optimization

  1. Reduce View hierarchy depth
  2. Use ViewStub for lazy loading
  3. Properly manage Activity lifecycle

Integration with Other Tools

ScenarioRecommended Tool
Java memory leaksLeakCanary + MAT
Native memory leaksAddressSanitizer
Frame rate optimizationPerfetto / Systrace
GPU analysisRenderDoc / Mali Graphics Debugger

Version Compatibility

Android VersionSupport StatusNotes
Android 4.0-7.x✅ Fully supportedSome data sources may be unavailable
Android 8.0-10✅ Fully supported-
Android 11-13✅ Fully supportedScudo allocator
Android 14-16✅ Fully supported16KB page support
Android 17+ / API 37✅ Fully supportedmemory-limiter evidence plus smaps SwapPSS/native allocator cross-checks

FAQ

Q: Why does smaps require Root?

A: The /proc/<pid>/smaps file requires privileged permissions to read. However, even without smaps, meminfo + gfxinfo can still provide sufficient information for effective analysis.

Q: What if hprof dump fails?

A: Ensure the application is debuggable or the device is rooted. You can also use --skip-hprof to skip hprof dump and use quick mode analysis.

Q: How to interpret "untracked Native memory"?

A: Untracked Native memory refers to the portion not recorded in meminfo's Native Allocations. It usually comes from:

  • Third-party libraries
  • Memory allocated directly using mmap
  • System allocations

If this portion keeps growing, there may be a Native memory leak.

References