I currently have a blank
LibGDX application that does nothing. It does not render anything, nor does it update anything. It is just an empty
Screen. When I deploy the application to android I am greeted with some horrifying memory consumptions. Using DDMS I create the following heap dump when the application is running on my device:
The most significant use of memory is the 13.163 MB 1-byte array allocation. Isn’t this half the heap?!
I checked the allocations and saw that nothing was pointing being allocated of that size:
Now using Eclipse MAT I analyse the heap dump:
So the high use of memory is still coming from byte arrays.
Analyzing the byte section further I come up with this:
I now see the huge byte allocations are coming from the android graphics. I’m not even drawing anything! Is there any way I can avoid having the android graphics portion of this app take up half of the heap. This just causes excess garbage collection to happen when things are actually going on, or is this normal and I just have to deal with it?
Note: I am running this on a Samsung Galaxy S4 with libGDX version 1.4 (or whatever the latest version is)
UPDATE: I have no discovered that the 14-13MB byte array allocation is normal for applications but I still have a problem. My heap size is too small. If the android graphics take up half of my heap I have little room for anything useful and the garbage collector goes crazy. On another application I created with an older version of libgdx (An undeniably more poorly coded application) and the heap size is 73 Mb. How can I increase the heap size? I presume 73 Mb is fairly large and as you can see most of it is not used. Here are the older application’s heap statistics:
After Android version 2.3, you cannot do anything about the size of the heap other than using android:largeHeap attribute.
There are two ways to cheat if you want a big heap not matter what:
- Using native api to allocate memory: Not a good idea as it increases complexity and if you are not planning to do things in native code,
- Allocating an unnecessarily big object before your execution to get a desired heap space: Although it will give you enough heap space once, it is not guaranteed that the heap size will stay the same.
However, initial heap size is not a problem if it gets resized when needed. My opinion about memory management in a game lifecycle is a little bit different than those two things listed above and what you are probably doing.
For a level, or a stage etc. you should not allocate memory at the exact time when you need it. This will not only cause stutters when allocating memory, but also stutter because of possible storage I/O. Anything, like sounds, graphics, fonts etc. should be prepared before a level. This is why a lot of games have a “loading” screen. You should prepare anything that you can do before starting the play.
For a small stage, doing this is OK -but still not good-. As things go complex, it will take the performance down. A lot of games (like sports games, racing games etc.) do the allocation before starting the game. Others do it as much as they can. Some open world games (like GTA) does not load all the map objects in the map, but they have a draw distance, so they draw as you move in the map and they remove the farthest objects from memory when the memory has no more room.[The reason why your app with older LibGDX version got more heap size is probably an allocation which caused an increase in the heap size and a deallocation which freed some of the heap so that you get a good 30% usage.]
You can assign this attribute value in the Android Manifest:
note, this will only work on Android 3.0+
Right-Click on allocated object, choose “trace to GC root”, “excluding weak references”