Lean & mean object pool in C#

2 comments

Posted on 8th April 2010 by Rod in C# |Game Programming |Programming

, , ,

I didn’t have time yesterday to post my daily info nugget so this post will be slightly longer and include a whole class definition!

An object pool is a great solution if you find yourself creating lots of objects that only live for a short period of time before being discarded (e.g. bullets fired by a 2D-shooter boss) which will eventually cause the garbage collector to kick in (every time 1MB is allocated) and slow things down.

What an object pool does is keep a pool of these objects and give us one when we ask for it and, once we are finished with it, return the object to the pool instead of destroying it. This benefits us in two ways:

  1. No memory allocation when we want a new object – we just ask the pool for one that is already instantiated;
  2. No extra garbage generated during the game loop.

In the world of game programming, we want everything to be as fast as possible so I’ve stripped my implementation of a generic C# object pool right down to the bare minimum.  The pool (which I’ve called FastPool) is fast and doesn’t try to be clever whatsoever.  Because of this, there are a few things to watch out for:

  1. The pool size is fixed when the pool is created;
  2. Pooled types require a default constructor (called when the pool is created);
  3. Requesting (fetching) an object from an empty pool will throw an exception;
  4. Releasing more objects back to the pool than it can hold will also throw an exception (you should never be doing this anyway or your logic is flawed);
  5. Releasing the same object multiple times or passing null to Release will result in pollution of the pool with unexpected results (again, you should never be doing this anyway or your logic is flawed).

Hope you find the source useful!

// FastPool.cs
// Feel free to use this source code any way you want apart from selling it.
// Rod MacDougall, Gallus Games
public class FastPool<T> where T : new() {
    private T[] pool;
    private int nextItem = -1;

    public FastPool(int capacity) {
        pool = new T[capacity];
        for (int i = 0; i < capacity; i++) {
            pool[i] = new T();
        }
    }

    public T Fetch() {
        return pool[++nextItem];
    }

    public void Release(T instance) {
        pool[nextItem--] = instance;
    }
}
2 Comments
  1. Roy Triesscheijn says:

    Aren’t the exceptions unneeded? I can imagine a pool for bullets that is of size 100 (usually you won’t need more). But in an insane fight you might need 101 bullets. Instead of throwing an exception when the pool is empty, why just not return a new object? Same for releasing, to many objects released (because of this new returning thing). Just ignore them.

    This of course would add two ifs to the pool, but I think this would be definitely worth that ‘penalty’.

    8th April 2010 at 1:27 pm

  2. Avoiding garbage collections on the compact CLR. | Olhovsky says:

    [...] Here’s another approach, which is minimalist, and still uses the new() constraint. This pool is clearly faster, but offers no way to iterate over over the collection of active pooled objects, and again, no abstract classes or constructors with parameters allowed. It’s also basically just an unsafe version of Stack [...]

    8th April 2010 at 6:24 pm

Leave a comment