Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (482)
Games in Android Showcase (110)
games submitted by our members
Games in WIP (548)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  [SOLVED] Garbage collection / Performance issues/ Out of Memory  (Read 4677 times)
0 Members and 2 Guests are viewing this topic.
Offline namrog84

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Posted 2012-11-28 20:23:46 »

So I have been working on an arcade/fast action lots of going on type android game.
Using libgdx for testing mostly on desktop, with occasional test on android

It was running mostly fine in all my tests, never had any issues.
But as my game has grown with complexity and number of entities

my game would crash occasionally, and I isolated it to a out of memory type of problem.

So one of the causes I thought was my massive amounts of 'new explosions' being called and allocating/destroyed many times a second, so my first thought was to build an ExplosionManager, that keeps them stored there, pulls one out randomly(unordered) uses it, and then sticks it back in there, and will add more if there are none left to give.  This way I could never call 'new' very often, and just keep a copy of it.

This solved my first problem.


But I noticed, it still happened on occasion. So I ran some trial runs, with no explosions, and such and still found some unusual behavior.  I believe that 1 of 2 things might be happening. My garbage collection isn't happening frequently enough and I need to make a Manager for everything, or something isnt going out of scope and thus being GC when it should be.

So Luckily, I recently discovered Java VisualVM (included with your SDK) and I love it.


http://84bit.com/gc.png

Although I have since limited the number of created entitiy bad guys. I first played for a little while., thus the 'growth' in the beginning, then I let my player die, and the bad guys just spawn/shoot/d to their thing

After running it idle for 15 minutes, it seems to be pretty consistent, thus memory is being handled pretty decently on its own.

However, most of the causes seems to point back to my floats is what is sucking up the most memory.

about 18 megabytes per 1k instances of float[],  isn't a float about 4 bytes?  So shouldn't this be more like 4-5 megabytes and not 15+?
I can't null them, and I am not sure if setting them to 0 when I am not using it, would help any.
Unless each float[] is a collection of floats, and not representing an actual float? Even though I have no defined float[] or even any collections of floats


Any suggestions on smoothing out performance spikes or helping the GC improve a little bit?
Especially with floats or entitymanagement?  (I originally and for the longest time, thought it was an issue with the textures/graphics) but it doesn't seem to be the case?

The biggest issue is when too much stuff is happening and there isn't enough time for GC to kick in, thus things overload the phone's memory.
There is plenty of memory on my desktop, but still a concern.


[SOLVED]
I was calling "new ShapeRenderer()" with every new entity on the screen, even though I wasn't using it.



"Experience is what you get when you did not get what you wanted"
Offline princec

JGO Kernel


Medals: 362
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #1 - Posted 2012-11-28 20:56:58 »

Well, what is that garbage that's being created constantly for a start? Do some heap snapshots.

Cas Smiley

Offline KittenKoder

Senior Member


Medals: 7



« Reply #2 - Posted 2012-11-28 21:44:32 »

This is a problem many programmers fail to address, so simply by paying attention I am impressed.

Check how many objects you are creating, then discarding soon after using it. If it's an object that you need to use a lot, you should consider creating long term "junk" versions of the object to use in method calls, because those objects will take up less memory, especially if the method is called a lot. When you leave a method call, or some such, the objects created are not immediately reclaimed by the system, the garbage collector does that, so they continue to use up memory until the garbage collection pass, which should be left to the system. Any object that is not a primitive can cause this.

I am no one else.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline sproingie

JGO Kernel


Medals: 202



« Reply #3 - Posted 2012-11-28 22:08:27 »

Here's the thing to remember about android's garbage collector: it really really sucks.  On the JVM you can make short-lived allocations all the live long day, and it'll be as fast as anything, you'll collect millions in microseconds on even a slow CPU.  With android, object pooling still the order of the day.  It's getting better, but it's still nowhere near as good as what you've got on the real JVM.
Offline namrog84

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Reply #4 - Posted 2012-11-28 22:41:28 »

princec, tomorrow when I am working on it again, I will take some heap snapshots and see what more closely is going on.
I haven't used the tool much before so wasn't quite 100% familiar with how to view things more 'indepth' of where the objects are originating from.

KittenKoder
I have an Array(libgdx) that uses to hold my main entitites, and in the above graph, I have it limited to about 20 bad guys at a time.
However, they are shooting bullets occasionally combined with the player's many bullets.
My main entity array on a super super busy screen with tons of stuff going on, will not have more than 400 entities, which includes all collideable objects.

Very very few noncollidable objects are ever created/destroyed

sproingie, I might have to do that ultimately, but I wasn't quite familiar with the tool enough to see what was causing the problems.


I take some heap snapshots and post my results tomorrow sometime.  Thanks for the tips thus far. I will continue to look into it more. 


Edit:

One last thing, having many sprites/entities being represented by images, is there any way I can track the image resources, because it seems that only cpu/ram is being reported in the included java visual vm thing.  Although I doubt its thats because i never see frame rate drop. Lastly I rarely use over 5% cpu so maybe I should reduce floats, increase ints and do more calculations to mask the Out of memory issue(heap size) issues


"Experience is what you get when you did not get what you wanted"
Offline Nate

JGO Kernel


Medals: 145
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #5 - Posted 2012-11-29 04:37:10 »

You can compare snapshots in jvisualvm. Create two snapshots, select both on the left, right click, compare.

On Android you can easily track allocations with the Android tools in Eclipse.

Offline Varkas
« Reply #6 - Posted 2012-11-29 10:49:42 »

If the actual problem is an "OutOfMemory" error, you might want to check your code for allocated objects which can't be garbage collected because there are still references to it.

Global (static) caches like lists or hashtables are infamous for not being cleared and keep objects from being garbage collected.

if (error) throw new Brick(); // Blog (german): http://gedankenweber.wordpress.com
Offline namrog84

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Reply #7 - Posted 2012-11-29 19:39:13 »

YAY! Solved

Before when I had even sometimes 20 bad guys, I was hitting 15+ megs minimum, sometimes up to 70, and if I spawned 200-300 I could easily hit 300-400 megabytes pretty quickly.


I created several object pools for bullets/projectiles/particles and then some for bad guys, trying to reduce the new
It improved a lot, but it was still horrendously slow


I was reading thru all my code when I noticed something REALLY stupid

I had  buried deep in my Entity base class
batch.end();
if(debug)
sr.begin() ... do shape render stuff
batch.start()

It was originally there for debugging my collision detection and realized, that even though it had long been shut off. It was still turning off/on the batch a lot, so I tried moving it into the debug statement

That improved performance a good bit, and started let me poking around more

One of the things I learned from the Java VisualVM, was that tons of floats were happening, and there were these collections of floats and stuff, from color, etc.. but it all seem 'gamestate' related, like libgdx stuff. I was confused why there was a good 50+ of them at 80kb each of tons of floats and other misc stuff that didn't seem to correlate to anything I had


Anyways, upon many stupid hours of figuring it out.
It was the silly ShapeRenderer
Even though I had encapsulated its method calls in my if(debug) boolean check
I had forgot to encapsulate the
new ShapeRenderer(); into something
It was actually being class level
ShapeRenderer sr = new ShapeRenderer(); 
so for Every single entity created, which there could have been 50-300 in my game. It was creating different shaperenders

I mean, I was well aware of the VERY first comment in the class "This class is not meant to be used for performance sensitive applications but more oriented towards debugging."

And I thought my debug had shielded it properly, anyways

FIXED

Even though it was a pain in the butt and broke my spirit a lot, for what ultimately was my own stupid mistakes.  I did learn a lot about creating object pools(I hadn't ever made them before) I also learned a lot about Java VisualVM and examining the heap and performance.(Ive never had to do performance inspection optimizations that much in the past)
I think it was worth it, because I learned an incredible amount of useful things to apply in the future! And I won't ever make that mistake again!



tl;dr;
1. My program now runs at 4-6 megabytes even with 400 bad guys on the screen.
2. Do not forget to remove "new Shaperenderer()" when you aren't debugging(or at least encapsulate it) Smiley and most definitely do NOT create a new instance of it with every entity created!!!

note:
(I had it over 1000 bad guys shooting, and having minor movement intelligence and didn't even break 10mb in my heap usage.) My game runs 1000x faster and smoother now. Whereas before when i hit 300 bad guys, i was at over 500 megabytes)






"Experience is what you get when you did not get what you wanted"
Offline Nate

JGO Kernel


Medals: 145
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #8 - Posted 2012-11-29 19:47:20 »

Mario tries to scare people away from ShapeRenderer, but it isn't so bad at all. You should generally only create one instance though as it is a little heavyweight, same as SpriteBatch.

Offline namrog84

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Reply #9 - Posted 2012-11-29 19:50:09 »

yeah, I hadn't meant to create instanced versions of it, I just had screwed up on that part, quite horribly. It was such a long time ago I had put it in there, I just completely forgot.

I still plan to use it for the exact purpose I was using it for, as its quite useful for seeing some shapes that represent non rendering objects, I just need to not make silly mistakes, by creating hundreds of it when there should be only one.

I had learned a while ago about keeping only one instance of SpriteBatch and also to not call begin/end too often, if possible.

Smiley

"Experience is what you get when you did not get what you wanted"
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

CopyableCougar4 (9 views)
2014-08-22 19:31:30

atombrot (28 views)
2014-08-19 09:29:53

Tekkerue (25 views)
2014-08-16 06:45:27

Tekkerue (23 views)
2014-08-16 06:22:17

Tekkerue (15 views)
2014-08-16 06:20:21

Tekkerue (22 views)
2014-08-16 06:12:11

Rayexar (61 views)
2014-08-11 02:49:23

BurntPizza (39 views)
2014-08-09 21:09:32

BurntPizza (31 views)
2014-08-08 02:01:56

Norakomi (37 views)
2014-08-06 19:49:38
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!