WCF Optimization and Service @ High Speed

Introduction

It has been a while since I was thinking of sharing some WCF service optimization techniques which we can easily implement as part of Service framework and service client side. This article talks about the following important points:

  • Client side Service Caching (Service Pooling)
  • Dynamic binding of Service
  • Object caching (Object Pooling)
  • Service instance management
  • Easy mapping Business objects in XML

There is nothing new in this article other than using C# list objects to cache services and objects from service. This includes an XML file which is easy to map objects and its types to create objects at run time using factory pattern.

The UML high level design picture shows everything explained in this article. I am sure we can do some more optimization in this project, but for the time being I just want to present a few areas where we can improve performance of Service Communication.

What is the Main Time Consuming Process in WCF Service Call?

One of the main time consuming processes in any service call or any call to the outside application boundary is initiating and opening the connection across the channel. That is where we need connection pooling. In WCF service call we can easily achieve with caching service channels at client side. This article gives you with channel caching and object caching to improve speed.

The following picture will clarify everything:

Solution

Prerequisites

You will need VS 2010 to open the Solution, but I am sure the same code will work in VS 2008 as well if you create another VS 2008 solution and add these files.

Solution Overview

If you look at the following picture, you can easily understand the different layers and files included. Probably you can download the attached code and dig into each file to get more about implementation.

Solution

Using the Code

The code below does Client side service caching. It is also tested with multi threading since multiple threads will be accessing cache collection object asynchronously. Hide   Copy Code

public static I CreateInstance<I>() where I : class
{
string endPointConfig = typeof(I).Name.ToString();
lock (_channels.SyncRoot)
{
if (_channels.ContainsKey(endPointConfig) == false)
{
_channels.Add(endPointConfig, OpenChannel<I>());
}
else if (((((IClientChannel)_channels[endPointConfig]).State == 
					CommunicationState.Faulted)) || 
	(((IClientChannel)_channels[endPointConfig]).State == 
					CommunicationState.Closed) || 
	(((IClientChannel)_channels[endPointConfig]).State == 
					CommunicationState.Closing))
{
//If the channel is faulted. The existing channel will be removed from the cache
//and recreate the channel again.
((IClientChannel)_channels[endPointConfig]).Abort();
((IClientChannel)_channels[endPointConfig]).Close();
_channels.Remove(endPointConfig);
_channels.Add(endPointConfig, OpenChannel<I>());
}
return _channels[endPointConfig] as I;
}
}       

This part of code is to create channel and open the channel. Hide   Copy Code

private static I OpenChannel<I>() where I : class
{
string endPointConfig = typeof(I).Name.ToString();
ChannelFactory<I> factory = new ChannelFactory<I>(endPointConfig);
factory.Open();
I channel = factory.CreateChannel();
((IClientChannel)channel).Faulted += new EventHandler(ServiceFactory_Faulted);
return channel;
}

This part of code gets executed when service is faulty and the same time we need to remove from Cache collection. Hide   Copy Code

static void ServiceFactory_Faulted(object sender, EventArgs e)
{
((ICommunicationObject)sender).Abort();
((ICommunicationObject)sender).Close();
Type typ = ((ICommunicationObject)sender).GetType();
lock (_channels.SyncRoot)
{
((ICommunicationObject)sender).Faulted -= new EventHandler(ServiceFactory_Faulted);
_channels.Remove(typ.Name);
}
}

This code part does object pooling and is used in Service host when a service invokes a business object.

ObjectFactory.cs

Hide   Copy Code

public static I CreateInstance<I>() where I : class
{
lock (_pooledObjects.SyncRoot)
{
if (_pooledObjects.ContainsKey(typeof(I)) == false)
{
_pooledObjects.Add(typeof(I), GetInstance<I>());
}
return _pooledObjects[typeof(I)] as I;
}
// return GetInstance<I>() as I;
}

That’s All About It – Quite Simple

I hope this approach is very simple and good to implement. Please have a look and if you like this article, please leave a vote and a comment. Thanks. Any comments and questions will be appreciated.

Points of Interest

I am always concentrating to deliver high performance applications with easy customized approach. I spent some time to tune WCF service with the help of many memory profilers like ants profiler.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)