1
\$\begingroup\$

I'm getting back into programming my game and I can see that I've used activities for so many things. I only have one with a custom-view (my actual game), the others are activities with XML-views, like menus, level-selector, Complete-screen etc.

My question is, Should I not use acitvities for this? and instead create states in my game with different touch-listeners? because I'm afraid of memory-leaks, which tends to come with the use of having activities everywhere.

I destroy all the activities properly before I move onto the next, but still, it feels sloppy somehow. Maybe the startscreen and levelselector are ok, since they are not called in real-time. But my complete-screen is called in real-time through the UI-thread, this just feels wrong.

My heap is already out of control and I dont need any leaks, I already have to limit my app to androids from 2012 and beyond.

So I'm calling out to someone with experience, since this is my first really big game, that I intend to release.

also, if anyone can tell me what these rows that I get in my logcat means, I would really appriciate it, I get that it has to do with heap and allocations, but what is good/bad to have here?

03-20 02:26:23.142: D/dalvikvm(21837): GC_FOR_ALLOC freed 941K, 8% free 14613K/15815K, paused 15ms, total 15ms

03-20 02:26:23.158: I/dalvikvm-heap(21837): Grow heap (frag case) to 17.825MB for 3686416-byte allocation

03-20 02:26:23.181: D/dalvikvm(21837): GC_CONCURRENT freed <1K, 7% free 18212K/19463K, paused 13ms+3ms, total 28ms

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Well, starting with the log lines you posted: those basically tell you that you don't have memory leaks "per-se" - you can't really have that with Java (well you can with Android Java if your'e careless with certain resources like image loading, but for most of the time you're fine).

What those lines describe is that at some point the garbage collector freed up some memory (line 1), than it follow by telling you that, from the whole chunk of memory available to your application an extra chunk has been made "active" (allocated as heap because instantiating something has made the previously allocated heap almost full) and finally the 3rd line is another garbage collect call which frees up some memory.

The Java-like "memory leaks" you can get with Android (and really any Java program) are really very different than those you can get with unmanaged languages (like C++): with C/C++ you get a memory leak if you consistently forget to free memory that you've manually allocated to instantiating some objects. With Java you can't manually allocate memory (the "new" operator in Java does this behind the scenes) and you absolutely have no way to manually free used memory (you can hint at it, but that's it). Since Java's heap is "freed" by the Garbage Collector automatically (and based on its own internal algorithms), what you can get is: if you create a lot of new objects in a short time (instead of reusing existing instances as much as possible), the Garbage Collector will be called more often to free your memory (followed by a behind-the-scene reallocation of heap for the new objects) and this can take time. It can get to the point where the GC uses 10-15% of the application CPU time, and results in visible slowdowns. Obviouslly, the first and easiest way to avoid this is to reuse your already created objects as much as possible (instead of creating new ones).

Coming back to your actual question: normally, the number of Activities you create will not have a dramatic impact on memory consumption and garbage collection time. That being said, you should balance the number of actual activities you have between having a decent logical organisation of your project and a decent GC occupation. Basically if your app has a handful of screens, you should make each one as a separate action. If however you find yourself making actvities for very small elements, which can just as well be displayed as pseudo-pop-ups and/or dialogs in an existing action, is better to refactor that code and "merge" those multiple small activities into a single one (with state-driven for the display of each of the contents of the previous activities).

The idea here is to make sure that:

  • there's really a lot of memory being used up and that's really an issue (you actually notice slowdowns because of it)
  • the extra memory is really due to action instanciation, and not due to other parts of your code (which create other types of instances)
  • try not to cut down to drastically on your activities, as this may also negatively impact your app: normally the OS deals with "passivation" and unloading of activities from memory when they're not used. However if everything is happening in one action, even if some contents is not needed at a given time, the OS will no longer be able to unload it
\$\endgroup\$
4
  • \$\begingroup\$ Thank you good sir! Very informative answer. I'm currently working on a method to re-use bullets so I dont have to add new ones, seeing as I fire 3 bullets/sec. Can you clearify what you mean by "Actions" as I'm very bad at proper terms in programming. \$\endgroup\$
    – Green_qaue
    Mar 20, 2013 at 14:59
  • \$\begingroup\$ OOps. Sorry. Most of the places where I wrote "Actions" I ment to say "Activities". Sorry. Tiread. At any rate, I had a similar problem with yours and it turned out it was the creation of too many in-game objects. As a thumb-rule: if you're creating new objects "by the game loop" (i.e certain situations can trigger object instantiation each game loop for several loops) - you need to stop that and reuse the instances. Also for collections and such, use arrays, avoid List, Set, Map etc. as it tons faster and less memory hungry. \$\endgroup\$ Mar 20, 2013 at 15:20
  • \$\begingroup\$ Ah, I suspected as much :) Yeah I'm working on reusing bullets like I said, and if I get that to work I will reuse enemies aswell. I'm using ArrayList for both, but might change to array, still have very poor understanding of how to reuse objects, but I'm googleing my brains out ^^ \$\endgroup\$
    – Green_qaue
    Mar 20, 2013 at 15:37
  • \$\begingroup\$ Oh well, it's no biggie. Just make a list of the average number of instance of each object you'll use. Instantiate them all at the beginning. Then reuse the heck out of them, and only create new ones for the fringe cases (like instantiate 10 bullets if that's the average you can see on screen, and only make extra instances for like the boss fights where the boss might shoot lots of extra bulletets as opposed to average). Also ditch ArrayList for plain old array. \$\endgroup\$ Mar 20, 2013 at 17:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .