Friday, February 11, 2011

Object Pool

Object Pool Design Pattern

Object pooling can offer a significant performance boost; it is most effective in situations where the cost of initializing a class instance is high, the rate of instantiation of a class is high, and the number of instantiations in use at any one time is low.

For example : We have a collection of pairs of shoes.. we took one from the shoe rack , after usage we will put it in the shoe rack. Again needed one, we may take another shoe from the same rack .. so that we can reuse the shoes from the currently availables free shoes..

Did you heard about Database Connection pooling ?  That technique is implemented using object pool pattern.

So the basic idea is  Instead of creating new new instances we will create a finite no of instances. Then pick one instance from the pool when needed. If there is no free instance in the pool then the client need to wait for getting one.

For creating Object Pool the following criterias should be there

  1. Create ObjectPool class with private array of Objects inside
  2. Create acquare and release methods in ObjectPool class
  3. Make sure that your ObjectPool is Singleton

C# Code sample


 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
namespace ObjectPoolmpl
{
    public sealed class MyPoolManager
    {
        private Queue poolQ = new Queue();
        private Hashtable tblPool = new Hashtable();
        private static readonly object objLock = new object();
        private const int PoolSize = 20;
        private int count = 0;
        private static MyPoolManager poolManager = null;
        /// <summary>
        /// Private constructor to prevent instantiation
        /// </summary>
        private MyPoolManager()
        {
        }
        static MyPoolManager()
        {
            poolManager = new MyPoolManager();
        }
        public static MyPoolManager Instance
        {
            get
            {
                if (poolManager != null)
                {
                    return poolManager;
                }
                return null;
            }
        }
        public void CreatePoolObjects(object obj)
        {
            object _obj = obj;
            count = 0;
            poolQ.Clear();
            tblPool.Clear();
            for (int objCounter = 0; objCounter < PoolSize; objCounter++)
            {
                _obj = new object();
                lock (objLock)
                {
                    tblPool.Add(_obj.GetHashCode(), _obj);
                    poolQ.Enqueue(_obj);
                    count++;
                }
            }
        }
        public bool AddObjectToPool(object obj)
        {
            if (count == PoolSize)
                return false;
            lock (objLock)
            {
                tblPool.Add(obj.GetHashCode(), obj);
                poolQ.Enqueue(obj);
                count++;
            }
            return true;
        }
        public object ReleaseObjectFromPool()
        {
            if (count == 0)
                return null;
            lock (objLock)
            {
                if (poolQ.Count > 0)
                {
                    object obj = poolQ.Dequeue();
                    tblPool.Remove(obj.GetHashCode());
                    count--;
                    return obj;
                }
                return null;
            }
           // return null;
        }
        public object ReleaseObjectFromPool(object obj)
        {
            if (count == 0)
                return null;
            lock (objLock)
            {
                tblPool.Remove(obj.GetHashCode());
                count--;
                PutInPoolAgain();
                return obj;
            }
        }
        private void PutInPoolAgain()
        {
            if (poolQ.Count > 0)
                poolQ.Clear();
            foreach (int key in tblPool.Keys)
            {
                poolQ.Enqueue(tblPool[key]);
            }
        }
        public int CurrentObjectsInPool
        {
            get
            {
                return count;
            }
        }
        public int MaxObjectsInPool
        {
            get
            {
                return PoolSize;
            }
        }
       
    }
    class Program
    {
        static void Main(string[] args)
        {
            //object obj1 = new object();
            //object obj2 = new object();
            MyPoolManager poolManager = MyPoolManager.Instance;
            //poolManager.AddObjectToPool(obj1);
            //poolManager.AddObjectToPool(obj2);
            //Console.WriteLine(poolManager.CurrentObjectsInPool.ToString());
            //poolManager.ReleaseObjectFromPool(obj1);
            //Console.WriteLine(poolManager.CurrentObjectsInPool.ToString());
            Console.WriteLine("Creating object Pool of size {0}" ,poolManager.MaxObjectsInPool);
            poolManager.CreatePoolObjects(new object());
            //for (int i = 0; i < poolManager.MaxObjectsInPool; i++)
            //{
            //    object obj2 = new object();
            //    poolManager.AddObjectToPool(obj2);
            //}
            object obj = null;
            for (; ; )
            {
                obj = poolManager.ReleaseObjectFromPool();
                if (obj != null)
                {
                    Thread.Sleep(1000);
                    Console.WriteLine("An Object Released :"+obj.GetHashCode().ToString());
                    Console.WriteLine("Current Objects in Pool :" + poolManager.CurrentObjectsInPool);
                    poolManager.AddObjectToPool(obj);
                    Console.WriteLine("An Object Addedd :" + obj.GetHashCode().ToString());
                }
                else
                {
                    Console.WriteLine("No more objects in the pool");
                    break;
                }
            }
            Console.ReadLine();
        }
    }
}


1 comment: