Do any of you write your own memory manager? That is, something similar to what you’d right for a C/C++ game where you keep track of memory usage, reference counting, deletion and the like. Do you find a similar module to be useful in your Java games, or do you simply let the garbage collector do it’s thing?
There are two lines of thinking here. The first that I have heard, but not actually used, is that since object deletion involves the garbage collector, some developers try never to delete an object, which essentially means that they don’t create temporary ones in loops.
To do that, you either make lots of objects at start time, or else use an object pool, where you request one from a whole bunch. Actually, an object pool is just a more organized way of doing things, but has limitations as well.
Is that the kind of memory management you mean?
Kinda… ;D
I’m thinking of a system where all game objects inherit from a base class. This base class has two static lists (live objects and dead objects). When an object is created it adds itself to this live list. Each object keeps a counter of references (other classes that are using it). When a class wants an object it gets it (how? I’m not sure yet) and calls its addReference method. This increments the counter. Once the using class if finished with the object it’ll call a remove method that would decrement the counter. If the counter is at 0, it moves to the dead list. The object also has a method clean that removes all objects from the deadList (sets them to null? I’m not sure).
Now the point of this is it keeps an object alive if it’s being used all around the code, and deletes it when no one else is using it. But that’s basically what the garbage collector does anyways. So it may be redundant.
Secondly, (this is from some C code if you couldn’t tell), a smart pointer is used to call the addReference and remove implictly so you didn’t have to remember such things (how you’d do that in Java I have no idea.)
There’s a lot more to this idea than what I just said, but that’s the gist of it. My main question is: is it worth it? Can any benefit be had from this implementation?
I wouldn’t do this until after you have determined that GC is causing you problems. There are enough options with the GC now … concurrent, parallel, incremental, plus eden size and such… that you shouldn’t need to do something so drastic.
Object pools are best used for objects that cost a lot in terms of resource allocation or construction time.
Ok, I didn’t think such code would really be needed. It seemed to be to be creating the garbage collector in C.
I’m not running into any memory issues right now either, with no memory management at all, nor am I running into garbage collector issues. I’m mostly just trying to see if people find a use for some sort of management system.
Is anyone out there using a memory management system in their application that they are happy about? Or is it pretty much (“don’t do anything stupid, like calling new in a for loop, and let the garbage collector handle the rest”)?
I tend to find that the best advice that has been given is as follows:
Write your code. Write it dirty.
MAKE NO ASSUMPTIONS ABOUT PERFORMANCE TILL YOU HAVE ACTUALLY PROFILED THE CODE.
From there, you can then decide which strategy to use for performance optimization.
A number of issues which have previously come up on the forums have actually vanished once the poster actually did some of this and discovered that what he thought was the problem actually wasn’t. And as swpalmer pointed out, the Java garbage collector is gaining a lot of intelligence with each release. So even if it is just a switch, it bears understand what the code is actually doing before one attempts to “fix” it.
My advice, therefore, is not to bother with a memory management model unless you prove that what you’re doing currently doesn’t work.
I am in agreement. I’ve never ran into any problems just dealing with calling new when needed and being done with it. I was just curious if anyone did anything “creative” that ended up being efficient and easy to use.
For server-side business programming I think there are very good answers to that question.
But in game programming, I have personally found that even amongst similar games the solutions HAVE to be different. Any solution in gaming seems to be inherently based on the game itself, making this question virtually moot.
It seems to me you’ll never be able to suggest any radical data structure model that gives you huge performance gains, because that data model is usually tied to the game it comes from. I have found in my experience it is far better to try to use real optimizations that have a solid foundation. For example, I gained a 15 to 1 performance increase by redrawing my images loaded from ImageIO at start time so that the hardware could accelerate them. This is based on the fact that Java doesn’t currently accelerate images loaded with ImageIO. Now there’s a performace gain that far offsets any data structure change I could have made.
Yet, others haven’t needed to do this, because their games are different. Perhaps they don’t use as many images, or they are rendering differently, or are so different from what I’m doing that they don’t need this kind of acceleration. So even in a performance optimization like this you can’t just blanket it (unless Sun does it in the JVM, because it seems like a good thing to just accelerate all images) to cover everyone.
[quote]Kinda… ;D
I’m thinking of a system where all game objects inherit from a base class. This base class has two static lists (live objects and dead objects). When an object is created it adds itself to this live list. Each object keeps a counter of references (other classes that are using it).
[/quote]
That’s essentially smart pointers. Something you see occasionally in the C++ world, except when the reference count hits 0 you delete the object. I can’t think of any true disadvantage to it, other than the grief of getting it up and running. But there must be some since it doesn’t seem to be all that common.
I can definitely recommend the book Java Platform Performance by Steve Wilson and Jeff Kesselman for some interesting insights on how the GC works, myths (the book pretty much debunks the whole “object pool” method), and various other things. It’s short and easy to read, I liked it.
There is no need for any of this memory management stuff in Java. Everything you might try and do is already being done extremely efficiently and accurately by the garbage collector already. The one thing that you might be worried about is object leaks, and using the JVM’s built in profiling interface and any one of a number of free profilers, you can find object leaks with ease.
The only situation I have come across where you need to do your own memory allocation management is when you have a large chunk of AGP ram that you want to carve up into little bits for buffers. You end up with a binary tree of memory allocations. But this is a very specialised case.
Cas
[quote][…]
Object pools are best used for objects that cost a lot in terms of resource allocation or construction time.
[/quote]
… like with JDCB SQL connection objects, for example. They can take long to be created Then you use a connection pool, but basically this is very similar to your mentioned object pool.
That sort of cost isn’t really memory allocation tho is it? Its normally to do with all the processing that needs to be done at initialisation (and/or network connections in JDBC).
Pooling for memory purposes (in Java) seems to have been regarded as generally pointless for some time.
Kev
FWIW, my game Cosmic Trip creates all objects at the start of a level and recycles ‘dead’ objects to prevent object creation and I really wish I didn’t do it that way. Although it’s all nice and smooth, I think I needlessly complicated things and I probably gained nothing.
Thanks guys, I’m glad to see my laziness paid off. I always suspected that the garbage collector was better than any crap I system I’d write to handle this stuff, now I know and don’t have to feel guilty.
If you’re serious about your game one kind of memory management you might want to do yourself is video memory management. Currently images are accelerated by Java2D on first come-first served basis, which might not be the way you want it - say, a back-buffer should take preference over some sprite which may be rendered to the screen only twice.
Unfortunately as of 1.4.2 there’s no good API to do this kind of management (other than Image.flush() and GraphicsDevice.getAvailableAcceleratedMemory()) but we’re hoping to change that in 1.5