How to release tiles loaded by AGSArcGISMapImageLayer?

1250
7
08-08-2017 02:41 AM
OliverHuber1
New Contributor

I'm integrating a lot of AGSArcGISMapImageLayers (20-30) by version 100.1.0 and now there is the problem that the loaded tiles are never released. The result is that my app crashes while zooming. Is there a possibility to release the loaded tiles by myself or is there an attribute that avoids 'caching'?

0 Kudos
7 Replies
MarkDostal
Esri Contributor

Thank you for your question!  A couple of things about what you reported:  The AGSArcGISMapImageLayer represents a dynamic map service, so there are no real "tiles" that get loaded.  What does get downloaded are the images generated by the service on the fly.  Those images are cached, but the caching is handled by iOS which provides a relatively small cache "space" for those, so I don't think that is the problem.

What device (or simulator) are you running the app on when you experience the crash?

Is it possible to share the map?  If so, I can try it and diagnose the problem here.

Also, have you looked at the "Memory Report" in the "Debug Navigator" inside Xcode when the app is running to determine just how much memory is being consumed?

Thanks,

Mark

0 Kudos
OliverHuber1
New Contributor

Thank you, Mark, for your answer. The memory leak exists on simulator and on the native device. As device and as simulator I tested with an iPad Air. The difference is only that the device crashes at 500MB of memory usage and the simulator is getting up to 2GB RAM. Regrettably, the service against I'm developing is a private service behind authentication. 

The crash only happens because of the memory leak. The memory usage of my app, especially of the map view controller, rises all the time. Even the memory is not released when the view controller is closed. So it is cumulated every time the controller opens.

All in all the the loaded map images are never released from memory. That's my problem.

Thanks,

Oliver

0 Kudos
MarkDostal
Esri Contributor

Oliver,  thanks for the updated information.  I will attempt to reproduce the problem here, using a bunch of AGSArcGISMapImageLayers.  I'll keep you posted...

Mark

0 Kudos
OliverHuber1
New Contributor

Mark, thanks for your support. I'm curious to hear from you.

Thanks,

Oliver    

0 Kudos
MarkDostal
Esri Contributor

Oliver,

I was able to reproduce, at least in part, the memory issues you are having.  I created a map with 20 `AGSArcGISMapImageLayer`s and displayed that in a mapView inside a UIViewController.  I ran the test with the v100.1 SDK in both the simulator and on an iPad Air.  The base memory usage was close to 300MB on the device.  After panning and zooming, the memory increased until the app crashed with an out-of-memory error.  It also crashed in the simulator, but only after consuming much more memory (as expected in the simulator).

I did NOT see any issue with memory failing to be released after closing the view controller.  In my test, I was replacing the map containing the 20 layers with a simple map:

self.mapView.map = AGSMap()

Since I was no longer holding onto the map with many layers nor any of the individual layers, those objects were released and the memory was freed.

I am still exploring options for you to potentially reduce the memory footprint of your map, either through settings on the `AGSArcGISMapImageLayer` or on the service(s) themselves.  When I have more information, I'll send it your way.

As for the memory not being released when you close the view controller, I'd suggest making sure that any reference to the view controller, the map view, and especially the maps and layers are released.  In the typical app, where a view controller has a map view, which contains a map with layers, if any one of those, from the VC on down, doesn't get released, then nothing below that in the chain will be released either.  I'm more than happy to look at any code or snippets you are able to share to help debug your issue.

Mark

0 Kudos
OliverHuber1
New Contributor

Hi Mark,

Sorry for my late answer, but I tried to analyze my problem a even more. 

Now I think that my problem is not that the images are not released, but there is to much RAM used by the framework. 

For example: My app starts and uses 80MB of RAM, than I start the map view controller and after that the app reserved nearly 200MB. When there are some images loaded from the map server by one zoomed out layer there are 220MB reserved. After zooming into detail the app reserved 240MB. That is the maximum for one layer, ok. The result for me is that one layer needs up to 40MB of RAM.

So now, I want to load more than 20 layers and that seams to be impossible. But if I load an image by a normal browser based http-client, the image is only 40KB big. My conclusion is that there has to be only 20*40KB -> 800KB reserved by the map, but there are gigabytes reserved. 

First I thought that perhaps there are also the feature information loaded but that is not. However, my new Question is, why does every layer needs such a lot of RAM and is there a possibility to reduce the RAM usage?

Next Point is that your idea, to replace the map to release everything when the map view is getting closed, does only work for some parts of the RAM usage. At all there are about 100MB left on the RAM. And if I start a new map view controller, the RAM usage is added above these 100MB. The result is that the RAM usage increases with every map view controller start and is never released. Could you reproduce that?

I have forgotten to tell you that I am using the objective-c framework 100.1.0.

Oliver

0 Kudos
dotMorten_esri
Esri Notable Contributor

Something to consider, when adding this many dynamic layers:

iPad screen resolution: 2048 x 1536 = 3145728 pixels.
Memory needed to hold a single exported image for one layer: 3145728 x 4 bytes = 12mb
So for 20 layers it adds up to around 250mb.
Then add that the previous image need to jump to the new image after a pan/zoom, so briefly you have the old and the new image in memory, so up to 500mb is used just for the raw exported map textures alone. That's not including all the other stuff needed, like the brief process of uncompressing the downloaded images, the layer data, map and mapview etc.

The behavior you're seeing where the mapview starts falling apart is very much what you see when you start exhausting your GPU resources. We have several internal processes in place to try and conserve memory used, but there's only so much one can do for certain layer types and maps.


On mobile devices (and in general) I really recommend keeping the number of image-based layers needed really low, and if possible merge the layers server-side. It'll also help you heavily reduce network traffic.

0 Kudos