mozilla-mobile/android-components

Tab thumbnails use too much memory

jamienicol opened this issue · 4 comments

Recently I've been doing some work to reduce the amount of memory used by webrender / graphics code (see bz-1780376). This was prompted by noticing that I could trivially crash Fenix on low-end devices by opening a couple dozen or so tabs, and I'm hoping it may help with issues such as mozilla-mobile/fenix#12731 as well. This has shipped in 105, and the crashing situation seems much improved. I suspect it may help with the background content processes being killed, but there are probably many other factors at play there too...

Anyway, whilst profiling memory usage I found that a huge amount of memory is used by android-component's tab thumbnails. See steps to reproduce and the screenshot below.

I note that we do have code to trim thumbnail memory usage in response to memory pressure here, but in my experience the memory pressure event is signalled too late to prevent background processes being killed. It would be better to avoid using too much memory in the first place, where possible.

cc @csadilek @jonalmeida

Steps to reproduce

  1. Build a debuggable (or profileable) build of fenix. Eg gradlew installNightly but with a debuggable line in local.properties
  2. Open Android Studio's Profiler tab
  3. Open Fenix on the device
  4. Click the + icon next to "Sessions" in the left-hand pane, then select the parent fenix process. (eg "org.mozilla.fenix", not the ":gpu" or ":tab" processes)
  5. Open eg ten tabs, waiting for the page to load each time. Watch the memory usage graph go up
  6. Select "Capture heap dump" and click "Record"
  7. Notice 100MB of Bitmap objects

Expected behavior

Memory usage remains at an acceptable amount.

Actual behavior

image

We can see that there are a whole bunch of Bitmap instances, each taking up just under 10MB. I think references to these are owned by both TabSessionState and ContentState hence why those objects appear in the list too.

Device information

  • Android device: Any, but I'm using a Pixel 6A
  • App (fenix, focus, ...): Fenix
  • App version: 107

┆Issue is synchronized with this Jira Task

And here's a zip containing the above profile, which can be unzipped then imported in to android studio.

thumbnails-profile.zip

Thanks for filing this @jamienicol !

I note that we do have code to trim thumbnail memory usage in response to memory pressure here, but in my experience the memory pressure event is signalled too late to prevent background processes being killed.

From what you've described it does indeed sound like the Bitmaps that we hold in memory for screenshots for each session and we are not clearing it quickly enough since we only clear them at this call. Since our thumbnails are rarely needed are full resolution in memory, what we can do is tell the BrowserStore to clear that immediately after adding them to disk. Then, when a feature (like the tabs tray) needs it, it can fetch the scaled down screenshot and use that only in memory (this is fine because the bitmap is destroyed when the UI/feature is done with it.

I think we can quickly prototype something for this soon and try it out since it would be a pretty big win.

Some things to note though is that while we are reducing memory pressure, we are increasing IO as a result (but at smaller cost). We (really me) should make sure that gesture navigation, which also uses high resolution thumbnails, still works and has no degraded effect.

I suspect though that this doesn't have a big impact on the tab reloading problem in Focus which still suffers from the bug but doesn't use thumbnails at all.