26 March 2011

Object Pooling


While writing eXtremecode's business layer, I found some performance related issues when creating a large number of business objects.
Each business object contains some heavy objects which require comparatively larger amount of system memory. Firstly I was creating these objects on each creation of business object, later I realized that these objects should be shared by related business objects, but that was not the solution as business objects were being created in different threads. Finally I decided to make a pool of similar objects so each thread could request pooled objects and could use them independently.

Pooling Source Code

/** 
Copyright (c) 2010, Sheikh Abdul Wahid Ahmed
Details @ http://extremecodeworld.codeplex.com/license
**/

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Threading;


namespace EXtremecode.Common
{
    public interface IPooledObject
    {
        ObjectPool Pool
        {
            get;
            set;
        }
    }
 
 public class ObjectPool
    {
        private Stack<IPooledObject> pool = new Stack<IPooledObject>();
        private int poolSize;
        private int numberOfPooledObjectsCreated = 0;
        private int timeOut = 15000; // in millisecond
        private Func<IPooledObject> CreateObject;
        private AutoResetEvent autoReset = new AutoResetEvent(false);
        private string poolName = string.Empty;

        public ObjectPool(Func<IPooledObject> CreateObject)
            : this("UnKnown", CreateObject, 10, 15000)
        {}

        public ObjectPool(string poolName, Func<IPooledObject> CreateObject)
            : this(poolName, CreateObject, 10, 15000)
        { }

        public ObjectPool(Func<IPooledObject> CreateObject
                , int timeOut)
            : this("UnKnown", CreateObject, 10 ,timeOut)
        { }

        public ObjectPool(string poolName, Func<IPooledObject> CreateObject
                , int timeOut)
            : this(poolName, CreateObject, 10, timeOut)
        { }

        public ObjectPool(string poolName,Func<IPooledObject> CreateObject
            , int poolSize, int timeOut)
        {
            this.CreateObject = CreateObject;
            this.poolSize = poolSize;
            this.poolName = poolName;
            this.timeOut = timeOut;
        }

        public IPooledObject GetObject()
        {
            while (true)
            {
                lock (pool)
                {
                    if (pool.Count > 0)
                    {
                        //get object from the pool.
                        Console.WriteLine("[{0}] PooledObject Poped  (Opened Objects [{1}])"
                            , poolName
                            ,numberOfPooledObjectsCreated - pool.Count);
                        
                        return pool.Pop();
                        

                    }
                    else
                    {
                        if (numberOfPooledObjectsCreated < poolSize)
                        {
                            //numbers of pooled object has not crossed the limit yet
                            //so create new object and return
                            IPooledObject pooledObject = CreateObject();
                            if (pooledObject != null)
                            {
                                numberOfPooledObjectsCreated++;
                                pooledObject.Pool = this; //add self reference
                                //which will be used to get the object back into pool again. 
                            }
                            Console.WriteLine("[{0}] PooledObject Created  (Opened Objects [{1}])"
                                , poolName
                                , numberOfPooledObjectsCreated - pool.Count);

                            return pooledObject;
                            
                            
                        }
                    }



                    Console.WriteLine("[{0}] Waiting for PooledObject", poolName);
                    bool timeOutOccured = !autoReset.WaitOne(timeOut); 

                    if (timeOutOccured)
                    {
                        throw new Exception(
                            string.Format("object request from the pool '{0}' has been timeout"
                            , poolName));
                    }
                }
               
                
            }
            
            
        }

        [System.Runtime.CompilerServices.MethodImpl
        (System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
        public void ReleaseObject(IPooledObject pooledObject)
        {
            pool.Push(pooledObject);
            autoReset.Set();
            Console.WriteLine("[{0}] PooledObject Pushed  (Opened Objects [{1}])"
                , poolName
                , numberOfPooledObjectsCreated - pool.Count);
        }
        
    }

    
}


Digg Google Bookmarks reddit Mixx StumbleUpon Technorati Yahoo! Buzz DesignFloat Delicious BlinkList Furl

0 comments: on "Object Pooling"

Post a Comment