Object Pool

As part of an exploration into game development patterns and techniques with Unity3D, I built out a basic demo of an object pool that I could try out on my laptop and phone.

For this example, I used the Cat Like Coding Object Pool Tutorial as a base to work from and pulled some simple assets out of the store to use as placeholders.

The basic setup of the demo is to create a fountain of objects with physics by arranging spawners in a ring and launching prefabs onto a sphere in the center. As objects fall off the sphere, they hit a kill zone underneath which returns the object to the pool.

Leveraging this technique I was able to maintain fairly smooth frame rates of over 30 FPS without any garbage collection issues or dropped frames. I even pushed a build to my iPhone 6 and experienced very good results running the simple app for over 10 mins.

What is an object pool?

An object pool is a design pattern that allows you to pre-allocate a reusable set of objects in advance rather than creating and destroying them right before they are needed.

As new objects are required, they are requested from the pool and, if available, one is returned immediately. In the case that one is not available, more objects are allocated to the pool in a sensible manner and one is returned from this newly allocated set.

When objects are no longer needed, they are returned to the pool to be reused for future requests without the allocation overhead.

How are object pools useful?

Object pools are commonly used to improve performance and memory use in situations where initializing an object can be costly.

Video games, simulations, and virtual reality experiences are all prime candidates for this pattern due to demanding requirements for maintaining high frame rates. This becomes even more of a challenge on mobile where resources are tightly constrained.

Filling these pools during loading screens or in parallel across frames rather than blocking to make the allocations is a bit of an art, but there are scenarios where the whole thing can be allocated at once. Some developers even go as far as pre-allocating all the memory their application will need in advance to avoid any hiccups due to garbage collection. 1

What is one way to implement an object pool?

Implementing a basic object pool is fairly simple. One way is to define a reference in your class for the pool this object belongs to.

Rather than destroy this object, implement a method that returns this object to its pool. This can be tracked with a simple boolean flag on the object or leveraging something build into your framework, such as using SetActive() in Unity3D.

The pool is just a collection of object instances and an index can be maintained to keep track of remaining supply in the pool. At some point, either when the pool is exhausted or passes some usage threshold, add more objects to the pool and update the index.

The last detail is calling and knowing when to call the return to pool method in your specific application.

What are some common things to watch out for?

There are a few considerations to be aware when implementing object pools. Caution should be exercised when resetting the objects in the pool for reuse so that objects are given from the pool in an expected state and sensitive information from the previous use of the object is not exposed.

Additionally, take care with empty pool scenarios and have a plan in place for replenishing the pool and ultimately throwing an exception when an upper bound has been hit.

Where can I find examples of this pattern in practice?

Object pools are used all over the place in most major frameworks. Connection pools, thread pools, and even pools for large, commonly used graphics objects such as fonts and bitmaps are implemented with reasonable defaults that can be tuned later by the developer based on actual usage statistics.

I would even go as far as to say that the expandable collections underlying the StringBuilder and generic List classes in .Net are special case implementations of this pattern, especially when used with the Clear() method for reuse.