-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[core,ios] Release more memory on entering background #11197
Conversation
Context cleanup must be called _after_ render sources release tiles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like a decent strategy to me, but can we rename onLowMemory
to minimizeMemoryUse
or something similar, since it's no longer being called strictly in low-memory situations?
52957fd
to
7909d71
Compare
👍 Renamed to @tobrun just as a heads up, this PR assumes that Android can release GL memory while in the background -- if that's true, Android will get a win from this PR because of b4fb4f6. If Android has a need to release memory more aggressively in the background, it would also probably be pretty straightforward to add an Android-targeted implementation that also discards the currently rendered tiles during a low memory event. |
Android still calls "reduceMemoryUse" only while handling a low memory event. iOS, on the other hand, calls "reduceMemoryUse" every time it enters the background.
Retain current render tiles for fast restart. Waiting for a memory warning doesn't work because we can't make GL release calls once we're in the background.
7909d71
to
496fddf
Compare
It’s hard to argue with those numbers. I’m slightly worried about the performance effect this might have on older devices, but obviously keeping ahold of memory doesn’t do any good if the app gets killed in the meantime. I’ll give this |
This also needs to be added to the iOS changelog (and hopefully included in #11152). |
The iOS SDK (#9203) and the Nav SDK (mapbox/mapbox-navigation-ios#963) both have issues tied to mbgl holding onto too much memory while in the background, causing iOS to kill the app. This PR tries to make some simple changes to ameliorate the situation:
onLowMemory
implementation that would prevent us from releasing abandoned buffers after clearing the in memory tile cache.Together these changes make it so that the memory used by the tile cache is effectively released when the app goes into the background. Tiles that are currently being rendered are still kept in memory, allowing a fast restart. If a low memory warning is received while in the background, we will try to clear the cache again, but it will effectively be a no-op.
How much memory will be released depends on the total size of tiles in the cache, but from playing around with the iosapp, it seems like navigating through city streets will tend to load up at least 50MB in the cache.
Before:

After:

(sharp drops represent switching to another app)
The cost of this change is that, after reloading, if you pan to a tile that would have been cached in memory, it will now require reloading/reparsing from disk. Just playing around on my phone I can't really tell the difference.
Further improvements?
Evacuate the GPU
A significant chunk of memory is still used by the tiles that are still being rendered at the time we enter the background. We don't want to throw away their data if we can avoid it because we want to be able to start rendering immediately on re-entering the foreground. It's possible we could implement a solution where:
glGetBufferSubData
to copy the data out into memory we manage.I don't know how significant the overhead of that copying would be, but I think it would add a fair amount of complexity.
Release other GL resources
I spent a little bit of time poking into releasing textures and framebuffers before we go into the background, since in most cases we can re-create them pretty quickly. I feel like I'm missing something, but even aggressively releasing all textures (without corresponding code to re-create/re-upload them) didn't seem to make a noticeable dent in memory usage. We could also try abandoning/re-creating programs and shaders -- I haven't looked into that at all.
/cc @bsudekum @friedbunny @kkaefer @jfirebaugh @lbud