default heading
Get a FREE SQL & MySQL DB- Starting at $4.95/month
ASP.NET 4/3.5 SP1, Classic ASP, Silverlight 4, MVC 2.0, AJAX URL Rewrite Module 2.0, Windows 2008 + IIS 7 Hosting, MS SQL & MySQL included, Visual Studio 2010 and Much More. Click Here and Sign Up Now!
Google


 

Article Rating:  3.65

Understanding Object Pooling in Microsoft .NET


In this article Joydip discusses what an Object Pool is and how we can implement one in .NET with the help of code examples in C#. Note: This article was originally published on AspAlliance.
By: Joydip Kanjilal Spacer Date: November 7, 2007Spacer <%--Download Spacer --%> Printer Friendly Version

Introduction

Object Pooling is nothing new. It is a concept that implies that we can store a pool of objects in memory to be reused later and, hence, reduce the load of object creation to a great extent. An Object Pool, also known as a Resource Pool, is a list/set of ready to be used reusable objects that reduce the overhead of creating each object from the scratch whenever a request for an object creation comes in. This is somewhat similar to the functioning of a Connection Pool, but with some distinct differences. This article throws light on this concept (Object Pooling) and discusses how we can implement a simple generic Object Pool in .NET.

What is an Object Pool?

An Object Pool may be defined as a container of objects that are ready for use. Lists of ready-to-be-used objects are contained in this pool. Whenever a new request for an object creation comes in, the request is served by allocating an object from the pool. Therefore, it reduces the overhead of creating and re-creating objects each time an object creation is required. "An object pool is an object that holds a list of other objects, ready to make them available for use (to yet another object, probably). It does the management work involved, like keeping track of which objects are currently in use, how many objects the pool holds, whether this number should be increased."

Why is an Object Pool required?

The biggest advantage of using Object Pooling is that it minimizes the consumption of memory and the system's resources by recycling and re-using objects as and when it is needed and serving the request for new objects from the pool of ready-to-be-used objects. The objects that the application is done with (the objects are no longer needed) are sent back to the pool rather than destroying them from the memory. According to MSDN, "Once an application is up and running, memory utilization is affected by the number and size of objects the system requires. Object pooling reduces the number of allocations, and therefore the number of garbage collections, required by an application. Pooling is quite simple: an object is reused instead of allowing it to be reclaimed by the garbage collector. Objects are stored in some type of list or array called the pool, and handed out to the client on request. This is especially useful when an instance of an object is repeatedly used, or if the object has an expensive initialization aspect to its construction such that it's better to reuse an existing instance than to dispose of an existing one and to create a completely new one from scratch."

How does an Object Pool work?

When an object is requested, it is served from the pool. When the object is disposed, it is placed back into the pool to await the next request that might come in at a later point in time. The pool initially consists of a number of objects. When a request for creation of an object comes in, the request is server from the pool of objects and the number of the available objects in the pool decreases by one. This process continues until the pool runs out of objects. The pool remains in memory as long as there is at least one object in the pool. The pool facilitates reusability and eliminates the overhead involved in creation of objects whenever they are requested. The following section discusses how an Object Pool (though somewhat similar to a Connection Pool) differs from a Connection Pool. You can find my article on Connection Pooling here.

How does Object Pooling and Connection Pooling differ?

There are distinct differences between Object pooling and Connection Pooling. Object Pooling is great in the sense that it can optimize access to expensive resources (like file handles or network connections) by pooling them in memory and reusing them as and when they are needed. According to MSDN, "Object pooling lets you control the number of connections you use, as opposed to connection pooling, where you control the maximum number reached."

Implementing an Object Pool in C#

We would design an object pool based on some predefined goals/objectives. These are stated as under the following.

  • Ease of use and reusable
  • Thread Safe
  • Type Safe
  • >Scalable
  • Configurable

These are the basic objectives that the pool should adhere to. With these in mind, we will now implement a simple Object Pool in C# and use this pool for creation, usage and destruction of objects.

The Pool Manager Class

The following code example illustrates how an object pool can be created. I have provided enough comments to enable the reader to understand how the Pool Manager class works. This class is based on the Singleton Pattern, i.e., there can be at any point of time only one instance of this class.

Listing 1

    1 using System;

    2 using System.ComponentModel;

    3 using System.Collections;

    4 using System.Threading;

    5 

    6 namespace ObjectPooling

    7 {

    8     /// &lt;summary&gt;

    9     /// A class to manage objects in a pool.

   10 

   11     ///The class is sealed to prevent further inheritence

   12     /// and is based on the Singleton Design.

   13     /// &lt;/summary&gt;

   14     public sealed class PoolManager

   15     {

   16         private Queue poolQueue = new Queue();

   17         private Hashtable objPool = new Hashtable();

   18         private static readonly object objLock = new object();

   19         private const int POOL_SIZE = 10;

   20         private int objCount = 0;

   21         private static PoolManager poolInstance = null;

   22 

   23         /// &lt;summary&gt;

   24         /// Private constructor to prevent instantiation

   25         /// &lt;/summary&gt;

   26         private PoolManager()

   27         {

   28 

   29         }

   30 

   31         /// &lt;summary&gt;

   32         /// Static constructor that gets

   33         ///called only once during the application's lifetime.

   34 

   35         /// &lt;/summary&gt;

   36         static PoolManager()

   37         {

   38             poolInstance = new PoolManager();

   39         }

   40 

   41         /// &lt;summary&gt;

   42         /// Static property to retrieve the instance of the Pool Manager

   43 

   44         /// &lt;/summary&gt;

   45 

   46         public static PoolManager Instance

   47         {

   48             get

   49             {

   50                 if(poolInstance != null)

   51                 {

   52                     return poolInstance;

   53                 }

   54 

   55                 return null;

   56             }

   57         }

   58 

   59         /// &lt;summary&gt;

   60 

   61         /// Creates objects and adds them in the pool

   62         /// &lt;/summary&gt;

   63         /// &lt;param name="obj"&gt;The object type&lt;/param&gt;

   64         public void CreateObjects(object obj)

   65         {

   66             object _obj = obj;

   67             objCount = 0;

   68             poolQueue.Clear();

   69             objPool.Clear();

   70 

   71             for (int objCtr = 0; objCtr < POOL_SIZE ; objCtr ++)

   72             {

   73                 _obj = new object();

   74 

   75                 lock(objLock)

   76                 {

   77                     objPool.Add(_obj.GetHashCode(),_obj);

   78                     poolQueue.Enqueue(_obj);

   79                     objCount ++;                             

   80                 }

   81             }

   82         }

   83 

   84         /// &lt;summary&gt;

   85 

   86         /// Adds an object to the pool

   87         /// &lt;/summary&gt;

   88         /// &lt;param name="obj"&gt;Object to be added&lt;/param&gt;

   89         /// &lt;returns&gt;True if success, false otherwise&lt;/returns&gt;

   90 

   91         public bool AddObject(object obj)

   92         {

   93             if(objCount == POOL_SIZE)

   94                 return false;

   95 

   96             lock(objLock)

   97             {

   98                 objPool.Add(obj.GetHashCode(),obj);

   99                 poolQueue.Enqueue(obj);

  100                 objCount ++;

  101             }

  102 

  103             return true;

  104         }

  105 

  106         /// &lt;summary&gt;

  107 

  108         /// Releases an object from the pool at the end of the queue

  109         /// &lt;/summary&gt;

  110         /// &lt;returns&gt;The object if success, null otherwise&lt;/returns&gt;

  111 

  112         public object ReleaseObject()

  113         {

  114             if(objCount == 0)

  115                 return null;

  116 

  117             lock(objLock)

  118             {

  119                 objPool.Remove(poolQueue.Dequeue().GetHashCode());

  120                 objCount --;

  121                 if (poolQueue.Count > 0)

  122                     return poolQueue.Dequeue();                   

  123             }

  124 

  125             return null;

  126         }

  127 

  128         /// &lt;summary&gt;

  129 

  130         /// Releases an object from the pool

  131         /// &lt;/summary&gt;

  132         /// &lt;param name="obj"&gt;Object to remove from the pool&lt;/param&gt;

  133         /// &lt;returns&gt;The object if success, null otherwise&lt;/returns&gt;

  134 

  135         public object ReleaseObject(object obj)

  136         {

  137             if(objCount == 0)

  138                 return null;

  139 

  140             lock(objLock)

  141             {

  142                 objPool.Remove(obj.GetHashCode());

  143                 objCount --;

  144                 RePopulate();

  145                 return obj;

  146             }

  147         }

  148 

  149         /// &lt;summary&gt;

  150 

  151         /// Method that repopulates the

  152         ///Queue after an object has been removed from the pool.

  153         /// This is done to make the queue

  154         ///objects in sync with the objects in the hash table.

  155         /// &lt;/summary&gt;

  156         private void RePopulate()

  157         {

  158             if(poolQueue.Count &gt; 0)

  159                 poolQueue.Clear();

  160 

  161             foreach (int key in objPool.Keys)

  162             {

  163                 poolQueue.Enqueue(objPool[key]);

  164             }

  165         }

  166 

  167         /// &lt;summary&gt;

  168 

  169         /// Property that represents the current no of objects in the pool

  170         /// &lt;/summary&gt;

  171         public int CurrentObjectsInPool

  172         {

  173             get

  174             {

  175                 return objCount;

  176             }

  177         }

  178 

  179         /// &lt;summary&gt;

  180 

  181         /// Property that represents the maximum no of objects in the pool

  182         /// &lt;/summary&gt;

  183         public int MaxObjectsInPool

  184         {

  185             get

  186             {

  187                 return POOL_SIZE;

  188             }

  189         }

  190     }

  191 }

Using the Pool Manager Class

The following code snippets in Listings 2, 3 and 4 show how we can use the PoolManager created in Listing 1.

Listing 2
object obj1 = new object();
 object obj2 = new object();
 PoolManager poolManager = PoolManager.Instance;
 poolManager.AddObject(obj1);
 poolManager.AddObject(obj2);
 MessageBox.Show(poolManager.CurrentObjectsInPool.ToString());
 poolManager.ReleaseObject(obj1);
 MessageBox.Show(poolManager.CurrentObjectsInPool.ToString());
 
 object obj = null;
 for(;;)
 {
       obj = poolManager.ReleaseObject();
       if(obj != null)
             MessageBox.Show(obj.GetHashCode().ToString());
       else
 
       {
             MessageBox.Show("No more objects in the pool");
             break;
       }
 }
Listing 3

object obj1 = new object();

object obj2 = new object();

PoolManager poolManager = PoolManager.Instance;

poolManager.AddObject(obj1);

poolManager.AddObject(obj2);

MessageBox.Show(poolManager.CurrentObjectsInPool.ToString());

poolManager.ReleaseObject(obj1);

MessageBox.Show(poolManager.CurrentObjectsInPool.ToString());

 

object obj = null;

 

for(;;)

{

      obj = poolManager.ReleaseObject();

      if(obj != null)

            MessageBox.Show(obj.GetHashCode().ToString());

      else

      {

            MessageBox.Show("No more objects in the pool");

            break;

      }

}

Listing 4

PoolManager poolManager = PoolManager.Instance;

ArrayList arr = new ArrayList();

poolManager.CreateObjects(arr);

 

object obj = poolManager.ReleaseObject();

MessageBox.Show("No of objects in Pool is: " +

    poolManager.CurrentObjectsInPool.ToString(),

    "The hash code of the released object is: " +

    obj.GetHashCode().ToString());

obj = poolManager.ReleaseObject();

MessageBox.Show("No of objects in Pool is: " +

    poolManager.CurrentObjectsInPool.ToString(),

    "The hash code of the released object is: " +

    obj.GetHashCode().ToString());

Note how we have used the PoolManager in the code listings above. The CreateObjects method has been used in Listing IV to create a specified number of objects of the ArrayList type and store them in the pool. However, the major drawback of this design is that there would be enough boxing and un-boxing overhead involved on storing and retrieving the objects to and fro from the pool. To eliminate this, I would recommend the usage of Generics. Further, the size of the pool (the maximum number of objects that the pool can contain) is also fixed and is not configurable. I leave it to the readers to make the necessary changes to the Pool Manager class to suit their needs.

References

Object Pooling [.NET Framework Developer's Guide -- MSDN]

How To Use Enterprise Services Object Pooling in Visual Basic .NET [MSDN]

Rediscover the Lost Art of Memory Optimization in Your Managed Code [MSDN]

Conclusion

Object Pooling is a mechanism that facilitates re-using of the existing objects in a pool (a container of live objects) rather than creating or re-creating them anew each time they are needed. This article has discussed the basic concepts of Object Pooling and how we can implement the same in .NET using C# as the language of choice. Stay tuned for more such articles on Object Pooling where I will discuss more on real-life implementation issues related to this concept. I hope readers will find this article helpful in giving a basic understanding of Object Pooling and how it works apart from implementing a simple Object Pool in C#.

 
Please Rate This Article Poor           Excellent
 
 
 
 
 
   © Copyright 2002-2010 DotNetJohn.com LLC
Terms of Use Privacy Policy