BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Design Patterns
.NET 2.0+

Object Pool Design Pattern

The object pool pattern is a creational design pattern that can improve performance when working with classes that are slow to instantiate. Rather than constructing new objects, reusable objects are retrieved from, and released to, a pool as required.

What is the Object Pool Pattern?

When you need to work with a large number of objects that are particularly expensive to instantiate and you only need each object for a short period of time, the performance of your entire application may be adversely affected. In these situations you might be able to use the object pool design pattern.

The object pool design pattern creates a set of objects that may be reused. When you need a new object you request it from the pool. If a previously prepared object is available it is returned immediately, avoiding the instantiation cost. If no objects are present in the pool, a new item is created and returned. When you have used the object and no longer need it, you return it to the pool, allowing it to be used again in the future without going through the slow instantiation process. It's important that once an object is returned to the pool that you no longer use any existing references. Doing so could cause unpredictable behaviour.

In some object pools the resources are limited so a maximum number of objects is specified. If this number is reached and a new item is requested, you may elect to throw an exception or block the thread until an object is released back into the pool.

The object pool design pattern is used in several places in the standard classes of the .NET framework. One example is the .NET Framework Data Provider for SQL Server. As SQL Server database connections can be slow to create, a pool of connections is maintained. When you close a connection it does not actually relinquish the link to SQL Server. Instead, the connection is held in a pool from which it can be retrieved when requesting a new connection. This substantially increases the speed of making connections.

Implementing the Object Pool Pattern

Object Pool Design Pattern UML

The UML class diagram above describes an implementation of the object pool design pattern. The classes in the diagram are described below:

  • Client. This is the class that uses an object of the PooledObject type.
  • PooledObject. The PooledObject class is the type that is expensive or slow to instantiate, or that has limited availability, so is to be held in the object pool.
  • Pool. The Pool class is the most important class in the object pool design pattern. It controls access to the pooled objects, maintaining a list of available objects and a collection of objects that have already been requested from the pool and are still in use. The pool also ensures that objects that have been released are returned to a suitable state, ready for the next time they are requested.

The following shows the basic code of the object pool design pattern implemented using C#. For brevity the properties of the classes are declared using C# 3.0 automatically implemented property syntax. These could be replaced with full property definitions for earlier versions of the language. Pool is shown as a static class, as it's unusual for multiple pools to be required. However, it's equally acceptable to use instance classes for object pools.

public class PooledObject
{
    DateTime _createdAt = DateTime.Now;

    public DateTime CreatedAt
    {
        get { return _createdAt; }
    }

    public string TempData { get; set; }
}

public static class Pool
{
    private static List<PooledObject> _available = new List<PooledObject>();
    private static List<PooledObject> _inUse = new List<PooledObject>();

    public static PooledObject GetObject()
    {
        lock(_available)
        {
            if (_available.Count != 0)
            {
                PooledObject po = _available[0];
                _inUse.Add(po);
                _available.RemoveAt(0);
                return po;
            }
            else
            {
                PooledObject po = new PooledObject();
                _inUse.Add(po);
                return po;
            }
        }
    }

    public static void ReleaseObject(PooledObject po)
    {
        CleanUp(po);

        lock (_available)
        {
            _available.Add(po);
            _inUse.Remove(po);
        }
    }

    private static void CleanUp(PooledObject po)
    {
        po.TempData = null;
    }
}

In the code above, the PooledObject includes two properties that are not shown in the UML diagram. One holds the time at which the object was first created. The other holds a string that can be modified by the client but that is reset when the PooledObject is released back to the pool. This shows the clean-up process on release of an object that ensures it is in a valid state before it can be requested from the pool again.

30 June 2013