Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GMSMapView: how to manage memory?

My app is using a GMSMapView in a subview, and memory usage is as follows:

  • 1.25 MB before map access;
  • 21.5 MB after first map access;
  • 30 MB (and sometimes spiking above 30) after zooming in and panning

No leaks, as far as I can tell with Instruments. The problem is, I am getting memory warnings, and often app shutdowns. Clearly, GoogleMaps is using the lion share of the app's memory. How can I release some of that in didReceiveMemoryWarning()?

Is it possible to have Google Maps in an app and manage its memory use, at least enough to prevent it from causing memory shutdowns?

This is GoogleMaps-iOS-1.3.0.

Update:

My memory figures were way off (was using Allocations Instrument instead of Activity Monitor). Here are the correct values:

  • 8.8 MB before map access
  • 57 MB after first map access
  • 65 MB, with spikes near 80 MB. after zooming and panning

This is clearly in the "trouble" range for a 256 MB RAM device (iPod Touch 4G, e.g.), and explains the memory warnings and occasional kicks.

Is anybody out there successfully running Google Maps in an app on a 256 MB device?

like image 671
user2444264 Avatar asked Jun 02 '13 00:06

user2444264


2 Answers

Try to use this code in your view controller:

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated] ;
    [m_mapView clear];
    [m_mapView stopRendering] ;
    [m_mapView removeFromSuperview] ;
    m_mapView = nil ;
}

I tried this and it does free up some GMSMapView memory .

like image 59
ArunMak Avatar answered Nov 15 '22 14:11

ArunMak


The maps API uses tiles which are 256 x 256 pixels in size. These are loaded into memory as 32 bits-per-pixel textures, so they will use 256 x 256 x 4 = 256kb per tile.

If you have an iPad which is 1024 x 768, then you'll need 4 x 3 = 12 tiles = 3MB. However this is only if your view happens to be perfectly aligned to tile boundaries - in practise it will cross boundaries, and so you'll probably need 5 x 4 = 20 tiles = 5MB.

However if you zoom out to almost the point at which the next lower zoom level would be displayed, each tile will be drawn at just over half its full size, and so you'll need 10 x 8 = 80 tiles = 20MB.

Then if you have a Retina device it will actually load the next higher zoom level's tiles and therefore require twice as many of them in each dimension (to match the screen's pixels not points), and so you'll need 20 x 16 = 320 tiles = 80MB.

Similar calculations for an iPhone 5 work out to 240 tiles = 60MB.

So, if you calculate the amount of memory which the map requires just for the tiles, not counting any overheads or other memory used for internal processing, it works out to quite a lot. So there's possibly nothing you can do. The maps SDK already frees unused tiles when there is memory pressure - but it can't free tiles which are required to render the current view.

That means your only option may be to reduce memory usage in your own code.

For my app I had to change the way it worked on an iPad 1, because it was running out of memory and crashing very often. For other devices I found it worked okay.

Some ideas for possible workarounds might be to reduce the size of the map view, or snap the zoom level to an integral value. Neither would be great for the user, but they might help avoid a crash.

like image 7
Saxon Druce Avatar answered Nov 15 '22 14:11

Saxon Druce