Proper memory management in OpenGL on Android devices

We have an application in which we draw a lot of things (mainly OpenStreetMap Tiles, as well as other images) with OpenGL ES 2.0. This works very well, but from time to time the application crashes without any information - this means: the application just closes, not a message about its failure, and there is also no message in logcat.

From the experiments we found out, the application crashes after loading too many textures in OpenGL ( glGenTextures/glBindTexture ) In the Samsung Galaxy S3 experiment, we can load up to 1800 textures of 256x256 size in the RGB888 standard. After that, our application crashes without errors. If we do not get the error ( GL_OUT_OF_MEMORY ), when do we constantly check OpenGL errors ( GLES20.glGetError ) when loading textures?

People usually ask: Is there a way to determine the maximum size available in gpu's memory, or at least how do we get a warning as soon as we run out of memory? (The problem is that we don’t know WHEN we should start deleting the descriptors, and we want to keep most of them as long as possible ...)

Thanks in advance for any answers.

+4
source share
1 answer

So, after some research, we found a solution.

But first of all: These methods will not help and will not be it . The methods mentioned in the first post will get completely useless numbers that won't help you at all and might not even be correct (since my galaxy S3 got a much higher number than link 7. But in our tests, link 7 could load the same amount or even more textures than S3).

Then we move on to our solution, which we are still not sure, is the best, but it will work:

It looks like you can store as many textures in OpenGL as you have full shared RAM. Yes, shared RAM, not a bunch, not something else related to your application! This is really the amount of free RAM for your entire system, there are no restrictions!

So, as soon as you realize that you have just read out the amount of free RAM that you have:

 ActivityManager actvityManager = (ActivityManager) mapView.getActivity().getSystemService( Activity.ACTIVITY_SERVICE ); ActivityManager.MemoryInfo mInfo = new ActivityManager.MemoryInfo (); actvityManager.getMemoryInfo( mInfo ); Log.v("neom","mema " + mInfo.availMem/1024/1024); 

The best place for this is probably in your onSurfaceCreated method or something like this. The amount of memory you receive is the total free RAM that you currently have. Basically, this value is too low, in almost any case, you can even allocate more memory than you are there (in our tests, we could always allocate 30-50% more RAM than availMem provided to us until the application tolerates failure (tested on Nexus 7 (+ 28%), Galaxy S3 (+ 36%), transformer T1 (+ 57%), Nexus S (+ 57%)). The reason for this is as follows: Android will free memory from unused material, background processes, etc., Before it really runs out of memory.

So what does that mean?

You can (almost) safely store as many texture bytes in OpenGL as you have RAM. For example: Suppose you have 375 MB of free RAM and textures, each of which is 256 KB in size, you can save about 1,500 textures in OpenGL before you start deleting some of them (with the LRU cache or something in it) kind). You could even save more, but I think you are safe enough with this amount.

Sureley, you could also get an availmem more often and just match the size of your cache or what you ever do with this new amount of memory - but I think that it’s enough if you do it once on onSurfaceCreated - especially since it will be read again if you switch to another application and vice versa.

+13
source

All Articles