[.net] New Objects and Memory Management in C#

Started by
8 comments, last by FoDDa 15 years, 9 months ago
Hi all I've been developing a top down space shooter game for a few weeks now (some of you may know from my posts in other catergories lol). My issue (as you may have guessed) lies in my use of new objects and managing the memory thereof. Example of my issue: In game, the user can (obviously) fire a laser to destroy other ships, asteroids etc. Currently, I have two ArrayLists to deal with my lasers: 1. Contains all the lasers currently active on screen 2. Contains references to the lasers that are now inactive, and need to be removed from the active laser ArrayList Each time the user presses the fire button, a new object of my Laser class is created in the arraylist. This class loads a texture and model file for the laser (texture is very small, as all work is done by my pixel shader). When the object is inactive (timedout or collided), it is removed from the ArrayList. The problem is, each laser that is created takes up another piece of memory. As the texture and model are very small, this doesn't create an issue in short term gameplay, however prolonged play sees the memory usage rise from 140mb exponentially. I have hit this issue before when destroying and creating asteroids, smoke sprites and enemy ships. I worked my way round it by specifying and loading a maximum number of each at the games load, and moving the required object to and from the required position when needed (eg: asteroid is destroyed: to create gibs, instead of creating two new asteroids, I scale and move the original asteroid, then take another asteroid from off screen and do the same thing) I know C# has a lot of automatic garbage collection, so am I not doing something correctly or is there another way of managing my memory better? I'd rather not keep using my workaround if it's possible! Any ideas? ------------- If you'd like to see the project in it's current state, there's some screenshots hosted on my website below http://www.olilittle.co.uk/forums/a121a.jpg http://www.olilittle.co.uk/forums/a121b.jpg
-=FoDDa=-
Advertisement
If your memory grows continually, it's because you're creating references and then keeping them around. You also might be starving the system so that the garbage collector doesn't have time to run (though IIRC it still will when you begin to peak out your memory). You *also* might be creating non-managed memory (textures/sounds) and not freeing them nicely.

Personally, I've only run into the first so don't really have much practical advice around the debugging of the other two.
Grab a profiler. There are lots of good ones with trials, and decent ones for free. They can usually help you track down nasty GC and memory related screwups.

It's hard for us to say without more information on your part.
Quote:Original post by Telastyn
If your memory grows continually, it's because you're creating references and then keeping them around. You also might be starving the system so that the garbage collector doesn't have time to run (though IIRC it still will when you begin to peak out your memory). You *also* might be creating non-managed memory (textures/sounds) and not freeing them nicely.



I'm pretty sure the garbage collector does have time to run, my memory usage jumps down by small amounts every now and then.

You do make two interesting points, If I am creating references and keeping them round, how can I remove them? The same question applies to the non-managed memory, how can I free it?

An extra bit of info:
When I add an object, I do the following
arraylist.Add(new Object(x,y,z,etc));

And when I remove it, I use
arraylist.RemoveAt(refnum);
-=FoDDa=-
When the GC runs, it will collect objects that do not contain any references to them (what it grabs depends on the generation of collection, but we won't go into that). The key thing there is "do not contain any references". Simply put, if your object contains no references (as in there is no way you could possibly reference to it again), it will become garbage and eventually be collected. In your arraylist example, if that is the only place the object is referenced, then that is all it takes. Example:

object o1 = new object(); // our object has a reference from our variable o1object o2 = o1; // now we have 2 references, o and o2o1 = null; // now we have one reference, o2o2 = null; // now we have no references. There is no way we can grab the object that o1 and o2 were referencing, so this object is now garbage. The GC will collect it automatically later.
NetGore - Open source multiplayer RPG engine
Spodi answered the first part. The only thing to add there is that having a method tied to an event is sufficient a reference (and usually where these things crop up unintended).

Quote:
The same question applies to the non-managed memory, how can I free it?


Usually the object will have some close() or similarly named method. Your API documentation should spell it out clearly.
Creating and destroying objects takes resources that you really don't have to spend if you really don't want to.

For objects like this my suggestion is to use using a pool of objects instead of creating them as needed.

The objects in the pool have a flag to tell you if they are in use or inactive. If in use, render them, if inactive, don't.

As you need them, just get the next inactive one, make it active, set it to do it's thing.

This keeps the whole creating and destroying objects to a minimum and will get rid of a bunch of overhead for you.

Also if you really want a List use List<t> instead of ArrayList, generics are your friends.

theTroll
Quote:This class loads a texture and model file for the laser (texture is very small, as all work is done by my pixel shader).


Probably a big one that I saw was you loading a texture for every laser. Why don't you just use a shared texture object for all of them. It would require a lot less memory.
Thanks for all the help guys, I'll have an investigate when i get home and see what works best for me i guess :)

TheTroll: I already have a pooling method for my explosion sprites etc, I was hoping to avoid using one for the lasers, but if it turns out to be the most effective idea Ill just have to use it anyway :)
-=FoDDa=-
dmoonfire: That's the sort of thing I was thinking I needed to do, however I don't really know how to create a shared texture for my objects to use. I do, at the moment, have a texture loading class that loads all my textures at game load, and is passed into my objects so they can use the loaded texture from that class instead of physically loading it off the harddrive (if that makes sense :)), is this a similar method?
-=FoDDa=-

This topic is closed to new replies.

Advertisement