Debugging Android Chrome Memory over USB
Android is the platform where the same V8 engine you profile on the desktop runs against a fraction of the memory, so it is the fastest way to find out which of your leaks actually matter. This page belongs to remote debugging memory on mobile browsers inside Browser DevTools & Performance Profiling Workflows.
| Symptom | Root Cause | Immediate Action |
|---|---|---|
Device listed as unauthorized |
Authorisation prompt not accepted | Reconnect and accept on the device screen |
No tabs under chrome://inspect |
Discovery off, or the device is asleep | Enable USB debugging and wake the screen |
| Capture takes several seconds and drops frames | Snapshot cost scales with device speed | Expect 3–5 s; drain interaction first |
| Trace goes flat halfway through | Screen locked, timers throttled | Keep the screen awake for the whole capture |
| Numbers do not match the desktop run | Different limits, pixel ratio and decode sizes | Compare structure, not absolute figures |
Root Cause: Same Engine, Different Budget and Different Interruptions
Android Chrome runs the same V8 you profile locally, which is the good news: retainer chains, constructor names and snapshot semantics are identical, and everything you know from a desktop heap snapshot transfers directly.
What differs is everything around the engine. The heap ceiling is set from device memory and is often a quarter of a desktop’s. Image decodes are larger because the device pixel ratio is higher, so the same gallery holds more bitmap memory. And the browser is a guest of the operating system: background tabs are frozen, timers throttled, and under pressure the renderer is discarded outright.
Those interruptions are what make mobile recordings hard to trust. A trace that flatlines for eight seconds usually means the screen locked, not that allocation stopped. A recording that ends abruptly usually means the tab was discarded. Neither shows up as an error in the DevTools UI, which is why the discipline is: screen awake, cable connected, short focused flows.
The capture cost is the last practical constraint. Walking the object graph is proportional to heap size and to memory bandwidth, so a snapshot that takes 900 ms on a laptop takes three to five seconds on a mid-range phone, with the page frozen throughout. Capture at a quiet moment, not in the middle of an animation.
Step-by-Step Fix
- Authorise the device. Command:
adb devices. Expected:R3CT90BCXXX device—unauthorizedmeans the on-device prompt was not accepted. - Open the target list. Path:
chrome://inspect/#devices→ Inspect. Expected: a DevTools window bound to the device tab, with the Memory tab available. - Quiesce before capturing. Stop animations and polling, and let the page idle for a few seconds. Expected: a flat memory counter before the capture starts.
- Capture with the screen awake. Path: Memory → Heap snapshot → Take snapshot. Expected: 3–5 seconds of frozen page on a mid-range device.
- Save and analyse on the desktop. Verification: the retainer chain in the saved file matches what you see in a desktop run of the same flow, confirming an application-level rather than device-level cause.
Command & Code Reference
Getting the device connected and confirming what you are actually profiling.
# 1. Is the device visible and authorised?
adb devices -l
# Expected: R3CT90BCXXX device product:... model:SM_G991B
# 2. Which Chrome build is on the device? Version differences change heap
# limits and default flags, so record this with the measurement.
adb shell dumpsys package com.android.chrome | grep versionName
# 3. What memory class does Android assign the device? This drives the
# heap ceiling Chrome chooses.
adb shell getprop dalvik.vm.heapgrowthlimit
adb shell cat /proc/meminfo | head -3
Keeping the screen awake for the length of a capture, which removes the most common source of a corrupted recording.
# Stay awake while charging over USB — the setting the DevTools docs assume.
adb shell settings put global stay_on_while_plugged_in 3
# Verify it took effect (3 = AC + USB + wireless).
adb shell settings get global stay_on_while_plugged_in
# Restore afterwards so the device behaves normally again.
# adb shell settings put global stay_on_while_plugged_in 0
Capturing the device’s own heap limits from the page, so the numbers can be compared honestly against a desktop run.
// Run this in the DevTools console attached to the device tab.
// jsHeapSizeLimit is what V8 chose for THIS device, and it is usually
// far below the desktop value that a local run reported.
const m = performance.memory; // requires --enable-precise-memory-info for exact values
console.log({
usedMb: (m.usedJSHeapSize / 1048576).toFixed(1),
totalMb: (m.totalJSHeapSize / 1048576).toFixed(1),
limitMb: (m.jsHeapSizeLimit / 1048576).toFixed(1),
dpr: window.devicePixelRatio, // drives decode and canvas cost
});
Verification & Regression Prevention
Verify the fix on the device, because the device is where the budget bites, but do the analysis on a saved snapshot at the desk. Opening a 200 MB snapshot in DevTools while it is still attached to a memory-constrained phone is a good way to lose the tab you were measuring.
For prevention, add the device’s own numbers — jsHeapSizeLimit and devicePixelRatio — to whatever telemetry you already collect from real sessions. Those two values explain most of the difference between “fine in testing” and “crashes for a segment of users”, and having them broken down by device class turns an anecdote into a target: if the 95th-percentile session on a ratio-3 device peaks at 80% of its allowance, that is a number a team can work against.
FAQ
Why does the snapshot take so much longer on a phone?
Capture cost scales with heap size and with how fast the device can walk the object graph, and a phone’s memory bandwidth and single-core speed are a fraction of a laptop’s. A capture that takes under a second on desktop routinely takes three to five on a mid-range Android device, during which the page is frozen.
Can I profile without a cable?
Yes, with adb over Wi-Fi, and it is convenient for short interactions. It is also less reliable for anything lasting more than a few seconds, because a dropped connection during a capture loses the whole snapshot. Use the cable for captures and wireless for quick inspection.
Do desktop numbers translate to the device?
The retention structure translates — the same object holds the same chain — but the absolute figures do not. Heap limits, device pixel ratio, image decode sizes and the eviction threshold all differ, so a leak that costs 20 MB on desktop can cost far more on a phone with a higher pixel ratio and a smaller allowance.
Related
- Remote Debugging Memory on Mobile Browsers — the parent guide and the bridge architecture
- Profiling Safari and iOS Memory with Web Inspector — the WebKit equivalent
- Canvas and ImageBitmap Memory in Long-Running Apps — why a higher pixel ratio costs so much more