Instance Pooling in WCF – Part 1

Posted: May 10, 2009 in WCF
Tags: , ,

In my earlier post on WCF behaviors I had given some code snippets on how we can implement pooling in WCF using Behaviors.In this series of posts I am planning to elaborate on the implementation on the same.So to start with the question What is Pooling? needs to be answered.Pooling is a technique where resources are recycled to avoid expensive creation and release of resources.Once the resources are recycled and sent back to pool they lose all their state and identity and are ready to be used again.

To start with first I have defined an interface IResourcePool which defines the contract to acquire and release an object back to the pool.

public interface  IResourcePool
{
    object Acquire();
    void Release(object resource);
}

The class ResourcePool is the implementation of IResourcePool.The four main properties driving the pool configuration are:

private Type resourceType = null; //The type of the resource to be pooled
private int maxPoolSize = 0; //Maximum number of instances that the pool can contain
private int initialSize = 0; // Initial number of instances to be present if we eager load the pool
private int incrementSize = 1;
//Number of instances to be added when all instances are in use

The ResourcePool class has the constructor accepting resource type,initial size and maximum size as shown below:

      public ResourcePool(Type resourceType,int maxPoolSize,int initialSize)
      {
          //Validate Arguments
          if (resourceType == null) throw new ArgumentNullException(“Type of the resource to be pooled cannot be null”, “resourceType”);
          if (resourceType.GetConstructor(Type.EmptyTypes) == null) throw new MissingMethodException(String.Format(“Type {0} should have a parameterless constructor”, resourceType.FullName));
          if (maxPoolSize <= 0) throw new ArgumentException(“MaxPoolSize should be greater than zero.”, “maxPoolSize”);
          if (initialSize <= 0) throw new ArgumentException(“InitialPoolSize should be greater than zero.”, “initialSize”);
          if (initialSize > maxPoolSize) throw new ArgumentException(“InitialPoolSize cannot be greater than MaxPoolsize”, “initialSize & maxPoolSize”);
          //Set pool properties
          this.maxPoolSize = maxPoolSize;
          this.initialSize = initialSize;
          this.resourceType = resourceType;
          //Eager Load the Pool
         EagerLoad(initialSize);
      }

The EagerLoad method creates the objects and pushes them into the stack.This stack is the in memory data structure used to keep track of the pooled instances.

private void EagerLoad(int eagerLoadCount)
{
    object  resource = null;
    resourceList = new Stack();
    lock (resourceLock)
    {
        for (int i = 0; i < eagerLoadCount; i++)
        {
            resource = Activator.CreateInstance(resourceType);
            resourceList.Push(resource);

            poolSize++;
        }
    }
}

There is another overloaded constructor as shown below which accepts the additional parameter incrementSize.

public ResourcePool(Type resourceType, int maxPoolSize, int initialSize, int incrementSize)
    :this (resourceType,maxPoolSize,initialSize)
{
    //Validate Argument
    if (incrementSize <= 0) throw new ArgumentException(“IncrementSize should be greater than zero.”, “incrementSize”);
    if (initialSize + incrementSize > maxPoolSize) throw new ArgumentException(“InitialPoolSize + IncrementSize cannot be greater than MaxPoolSize.”, “incrementSize”);

    //Set pool properties
    this.incrementSize = incrementSize;
}

Now in this we have two more interesting properties related to the pool configuration:

private bool isEvictionEnabled = false; //To remove objects from the pool after certain period of inactivity
private int evictionInterval = -1;
//Interval after which objects needs to removed.

The third constructor shown below accepts these two as as parameters:

public ResourcePool(Type resourceType, int maxPoolSize, int initialSize, int incrementSize, bool isEvictionEnabled, int evictionInterval)
    :this (resourceType, maxPoolSize, initialSize, incrementSize)
{
    //Validate Argument
    if (isEvictionEnabled && evictionInterval <= 0) throw new ArgumentException(“Eviction interval must be greater than zero when Eviction is enabled.”, “evictionInterval”);
    //Set pool properties
    this.isEvictionEnabled = isEvictionEnabled;
    this.evictionInterval = evictionInterval;
}

The method used to acquire objects from pool is a simple one which checks the instance count in the pool and pops an object from the underlying stack and reduces the count by one.

public object Acquire()
{
     object  retVal = null;
     //Lazy Load
     if (resourceList.Count ==0)
     {
         if (poolSize == maxPoolSize) throw new InvalidOperationException(“MaxPool Size has exceeded”);
         if (poolSize + incrementSize > maxPoolSize)
         {
             EagerLoad(maxPoolSize – poolSize);
         }
         else
         {
             EagerLoad(incrementSize);
         }
     }
     lock (resourceLock)
     {
         retVal = resourceList.Pop();
         lastAccessed = DateTime.Now;
     }
     return retVal;
}

The method used to Release an object back to the pool just does the reverse:

public void Release(object resource)
      {
          TimeSpan diff ;
          if (resourceType != resource.GetType())
          {
             throw new ArgumentException(String.Format(“Invalid object type.{0} is expected”, resourceType.FullName), “resource”);
          }
          if (!isEvictionEnabled)
          {
              lock (resourceLock)
              {
                  resourceList.Push(resource);
              }
          }
          else
          {
              diff = DateTime.Now – lastAccessed;
              if (diff.Minutes >= evictionInterval)
              {
                  Evict();
              }
              else
              {
                  lock (resourceLock)
                  {
                      resourceList.Push(resource);
                  }
              }
          }
      }

So with this simple pool implementation in place in the next post we will see how to plugin to the WCF framework.

Advertisements
Comments
  1. maruti says:

    Good news for dotnet guys who wants to learn new things from elearning ,
    Here is a link for exclusive freely downloadable videos on latest microsoft technologies like dot net 3.5,we are updating this daily

    just click on link below or copy and paste link to ur browser

    http://www.elearningfromhome.com/Sample_Videos.html

  2. Robert says:

    Thanks

    It was very useful

    But The implementation of the method Evict();

    What should I do in Evict

    Thanks again

  3. Robert says:

    resourceList.Clear(); // Evict();
    poolSize = 0;
    }

    I did this two is that ok

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s