I've been chugging away at the code lately fixing memory leaks as I go along. I posted this thread on reddit yesterday and got some great advice.
First off, XNAs garbage collection is pretty bad. Even when I thought I was deleting objects from memory, I more than likely wasn't.
The first type of solution for this is reuse. I was already instantiating as little new objects as possible but it was due to performance issues. Instantiating an object takes CPU and it's a waste when you can use an old one. I wanted to make sure I did it as little as possible, so I went through the code with a fine toothed comb and took out even more new objects.
The second thing I did was create object pools. Whenever a new chunk needs to be created, I instantiate it and then build() it. Inside of build(), I instantiate up to 32,768 (a completely full chunk) new cubes. When I'm done with a chunk, I remove those cubes and then remove the chunk from memory. Or at least I thought I was doing that (damn you XNA).
With an object pool, I am still requesting a new cube. This time I'm requesting it from the pool though. For the first several chunks, I am instantiating a new object each time. The difference is when I delete a chunk. Instead of removing it from memory, I mark it as 'free'. The pool notices this and the next time I request a chunk, it resets the values in this free one and gives me that instead. The same thing happens with the cubes. This means that instead of creating several million new cube() instances throughout the game life, I'm only create a couple hundred thousand that are reused over and over again.
After setting that up, I'm still having some issues that I've narrowed down to be threading problems. I decided to change how I use threads. Beforehand, I had 3 threads. 1 for the main game, 1 for the delete chunks functionality and 1 for the add chunks functionality. I decided to combine the delete chunks and add chunks functionality into 1 thread so I was always referencing the pool from the same thread (removing any threading issues).
While I haven't perfected it yet, my memory footprint is drastically lower. I'm going to spend this week hopefully focusing on that and perfecting it. No new gameplay additions will happen until I figure this out.
First off, XNAs garbage collection is pretty bad. Even when I thought I was deleting objects from memory, I more than likely wasn't.
The first type of solution for this is reuse. I was already instantiating as little new objects as possible but it was due to performance issues. Instantiating an object takes CPU and it's a waste when you can use an old one. I wanted to make sure I did it as little as possible, so I went through the code with a fine toothed comb and took out even more new objects.
The second thing I did was create object pools. Whenever a new chunk needs to be created, I instantiate it and then build() it. Inside of build(), I instantiate up to 32,768 (a completely full chunk) new cubes. When I'm done with a chunk, I remove those cubes and then remove the chunk from memory. Or at least I thought I was doing that (damn you XNA).
With an object pool, I am still requesting a new cube. This time I'm requesting it from the pool though. For the first several chunks, I am instantiating a new object each time. The difference is when I delete a chunk. Instead of removing it from memory, I mark it as 'free'. The pool notices this and the next time I request a chunk, it resets the values in this free one and gives me that instead. The same thing happens with the cubes. This means that instead of creating several million new cube() instances throughout the game life, I'm only create a couple hundred thousand that are reused over and over again.
After setting that up, I'm still having some issues that I've narrowed down to be threading problems. I decided to change how I use threads. Beforehand, I had 3 threads. 1 for the main game, 1 for the delete chunks functionality and 1 for the add chunks functionality. I decided to combine the delete chunks and add chunks functionality into 1 thread so I was always referencing the pool from the same thread (removing any threading issues).
While I haven't perfected it yet, my memory footprint is drastically lower. I'm going to spend this week hopefully focusing on that and perfecting it. No new gameplay additions will happen until I figure this out.
1 comment:
The real character of a man is found out by his amusements.
Post a Comment