Tuesday, June 30, 2009

Fast version of the Activator.CreateInstance method using IL

Posted on/at 7:37 PM by Admin

 

FastObjectFactory.zip (50.35 kb)

Source: http://mironabramson.com/blog/post/2008/08/Fast-version-of-the-ActivatorCreateInstance-method-using-IL.aspx

 

 

We all know (I guess) the method Activator.CreateInstance(Type) and the generic version:  Activator.CreateInstance<T>()  that are used to create an instance of a specified Type.

In now days all are talking about 'Entity-relationship model' , 'Object-relational mapping' and that stuff, that basically it means getting a IDataReader, loop over it and fill with the data a List with specfied type of objects and return a List instead of DataSet or DataTable (or similar mechanism). While looping over the IDataReader, every iterate, an instance of the specified type needs to be create. It can be done using one of the methods above, but it can be improved by usind IL and some help using some cache. Here is how can it be done:

public static class FastObjectFactory
{
private static readonly Hashtable creatorCache = Hashtable.Synchronized(new Hashtable());
private readonly static Type coType = typeof(CreateObject);
public delegate object CreateObject();
/// <summary>
/// Create an object that will used as a 'factory' to the specified type T 
/// <returns></returns>
public static CreateObject CreateObjectFactory<T>() where T : class
    {
        Type t = typeof(T);
        FastObjectFactory.CreateObject c = creatorCache[t] as FastObjectFactory.CreateObject;
if (c == null)
        {
lock (creatorCache.SyncRoot)
            {
                c = creatorCache[t] as FastObjectFactory.CreateObject;
if (c != null)
                {
return c;
                }
                DynamicMethod dynMethod = new DynamicMethod("DM$OBJ_FACTORY_" + t.Name, typeof(object), null, t);
                ILGenerator ilGen = dynMethod.GetILGenerator();
                ilGen.Emit(OpCodes.Newobj, t.GetConstructor(Type.EmptyTypes));
                ilGen.Emit(OpCodes.Ret);
                c = (CreateObject)dynMethod.CreateDelegate(coType);
                creatorCache.Add(t, c);
            }
        }
return c;
    }
}

Note the static HashTable is been used as a cache. The first  time we create a delegate 'CreateObjec' for the given type it is 'slow', so all the point here, is to cache this delegate. The next time we need to create an object from the given type, the 'CreateObjec' delegate will be used from the cache. Without caching it, the whole story worth nothing.

Here are some benchmarks:

1 Object:


100 Objects:

1000 Objects:

Comparing to the generic constraint : new()

Below there is the small project I used for the benchmarks:

FastObjectFactory.zip (50.35 kb)

Source: http://mironabramson.com/blog/post/2008/08/Fast-version-of-the-ActivatorCreateInstance-method-using-IL.aspx

0 comments:

Post a Comment

About Me

Developers house is a blog for posting technical articles in different technology like Microsft, Java, Oracle ..etc Microsoft technology includes c#,VB.net,ASP.net,Ajax,SilverLight,TFS,VS.NET 2003,2005,2008,2010 , SQL Server 2000, 2005 , Expression Blend , ...etc I hope it is helpful for all of you and if you are interested to post articles on it, only send me at ahmad.eed@gmail.com