About the author

Miron Abramson
Me
Software Engineer,
CTO at PixeliT
and .NET addicted for long time.
Open source projects:
MbCompression - Compression library

Recent comments

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2009

Creative Commons License

Blog Flux Directory
Technology Blogs - Blog Top Sites

Fast version of the Activator.CreateInstance method using IL

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)

Currently rated 5.0 by 6 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: C# | Performance | IL
Posted by Miron on Saturday, August 09, 2008 12:52 PM
Permalink | Comments (17) | Post RSSRSS comment feed

Related posts

Comments

m goode us

Monday, November 17, 2008 8:10 AM

m goode

Can this command be used on the Motorola Krave? I would love to see if it could! I became a big fan of the krave not too long after I started working with Motorola. Has anyone seen the features online? (motorola.com/krave) My favorites are the 2 MP camera and touch screen. It's definitely worth checking out.

Damien McGivern gb

Sunday, November 23, 2008 9:50 PM

Damien McGivern

Hi,

I'm just wondering why you don't use the generic constraint : new() which would require the type being created has a constructor with no parameters, as this is what the generated IL code is looking for, this way you're not using reflection at all.

Damien

Miron il

Sunday, November 23, 2008 11:22 PM

Miron

@Damien,
Can you give an example for what your mean?

Damien McGivern gb

Monday, November 24, 2008 1:13 AM

Damien McGivern

see http://msdn.microsoft.com/en-us/library/sd2w2ew5(VS.80).aspx

example

class ItemFactory<T> where T : new()
{
public T GetNewItem()
{
return new T();
}
}

Miron il

Monday, November 24, 2008 8:53 AM

Miron

@Damien,
Thats will be exactly the same as Activator.CreateInstance<T>() (even worse performance)
The point is using IL to improve the object creating performance.

Damien McGivern gb

Monday, November 24, 2008 11:37 AM

Damien McGivern

Miron, you're incorrect. Activator.CreateInstance<T> may look like the example I gave earlier but Activator.CreateInstance<T> doesn't use the generic new() constraint meaning it has to use reflection to create the object. Generics doesn’t use reflection at all, instead it simple won't let you compile code that doesn't follow its rules - this is why in the background the generic code can call the constructor directly as it's guaranteed to be there. To prove my point run the code below and you'll see that using the new() constraint is about a quarter faster that the IL and it has the added bonus of being type safe and not requiring a cast.

On my laptop the example below results in timings of 0.0159353 and 0.0202851 for the new() constraint and the IL code respectively.



using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection.Emit;

namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
const int max = 9999;

var sw = new Stopwatch();



Console.WriteLine("Generic new constraint"Wink;
sw.Start();
var factory1 = new ItemFactory<Test>();
for (int i = 0; i < max; i++)
{
Test f = factory1.GetNewItem();
}
sw.Stop();

Console.WriteLine(sw.Elapsed);


Console.WriteLine("IL code"Wink;
sw.Start();
FastObjectFactory.CreateObject factory2 = FastObjectFactory.CreateObjectFactory<Test>();
for (int i = 0; i < max; i++)
{
var g = (Test) factory2();
}
sw.Stop();

Console.WriteLine(sw.Elapsed);

Console.Read();
}

#region Nested type: FastObjectFactory

public static class FastObjectFactory
{
#region Delegates

public delegate object CreateObject();

#endregion

private static readonly Type coType = typeof (CreateObject);
private static readonly Hashtable creatorCache = Hashtable.Synchronized(new Hashtable());

/// <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);
var c = creatorCache[t] as CreateObject;
if (c == null)
{
lock (creatorCache.SyncRoot)
{
c = creatorCache[t] as CreateObject;
if (c != null)
{
return c;
}
var 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;
}
}

#endregion

#region Nested type: ItemFactory

private class ItemFactory<T> where T : new()
{
public T GetNewItem()
{
return new T();
}
}

#endregion

#region Nested type: Test

private class Test
{
}

#endregion
}
}

Miron il

Monday, November 24, 2008 12:24 PM

Miron

@Damien,
You missed the most important part in your benchmark- caching the 'CreateObject ' object. The first time will be slow (of-course) but since it is in the cache - it will be much faster than any other 'Object factory'.
Also, I attached screen shot of benchmark with the generic constrain new(), and surprisingly , it is even slower than Activator.CreateInstance<T>() and much slower than the IL code - after it was cached.
You can download the source code - it include the whole benchmarks code.

Damien McGivern gb

Monday, November 24, 2008 10:42 PM

Damien McGivern

@Miron I stand corrected, the IL code is much faster than the generic new() constraint. My test benchmark code wasn't calling the Reset on the stopwatch, D'oh - that'll teach me to post late night code.

We use the new() constraint in a key part of some code at work. We cache the reflection code for populating our business objects but not their creation, after this exchange we will be now.

Although I've rewritten this code so that it no longer requires caching, locking, casting and is type safe at compile time:


public static class FastObjectFactory2<T> where T : class, new()
{
public static Func<T> CreateObject{get; private set;}

static FastObjectFactory2()
{
Type objType = typeof(T);
var dynMethod = new DynamicMethod("DM$OBJ_FACTORY_" + objType.Name, objType, null, objType);
ILGenerator ilGen = dynMethod.GetILGenerator();
ilGen.Emit(OpCodes.Newobj, objType.GetConstructor(Type.EmptyTypes));
ilGen.Emit(OpCodes.Ret);
CreateObject = (Func<T>WinkdynMethod.CreateDelegate(typeof(Func<T>Wink);
}
}

Moving the generic parameter from the method to the type creates a unique factory type for each object type we are trying to create. This means we can make the delegate static. So we move the IL method creation into the factory static constructor meaning it is only ever called once. I've added the generic new() constraint although I don't use this to create the object it does ensures that there is a public constructor with no parameters at compile time making the code that bit more safe. I’ve also exposed the generic type in the creation delegate removing the need to cast. With these improvements you get an increase in performance over the original IL code and cleaner code.


watch = Stopwatch.StartNew();
var create3 = FastObjectFactory2<MyObject>.CreateObject;
for (int i = 0; i < MAX; i++)
{
MyObject myObj = create3();

}


What do you think?

Miron il

Monday, November 24, 2008 11:22 PM

Miron

@Damien,
You got it Damien!
Very nice and clean code indeed. Smile
Even that your code gives the same performance as my original IL code (even when using the casting), it is cleaner
and more important - it is type safe.
I will update our code too!
Thanks

m goode us

Tuesday, November 25, 2008 7:39 AM

m goode

I like this code. Does anyone know how programming languages work for cell phones? I'm interested to see how technology for touch screens work. I've been working with Motorola recently and have became a huge fan of the Krave. I love the touch screen functionality and 2 MP camera. It's incredible! Check it out online at Motorola.com/krave.

Damon Wilder Carr us

Thursday, November 27, 2008 8:17 AM

Damon Wilder Carr

Don't get me wrong here... I love geeky performance tweaks.. But are you saying this was a 'fix' for a showstopper performance problem for any known application now or ever previously created on the .NET platform? Is this in any way solving a problem that merits the added complexity introduced? In my world I am measured on the fact that 80% of software budgets go to maintenance, not new dev, and performance optimization is verbotten until there is a darn good reason to bring it up.

It is was, I would tend to thing many nastier things are at work then a simple newobj opcode.

Damon

P.S. Why not write a language? Then you can use compiler optimizations and constructs you introduce to optimize every last cycle? I'm not even being sarcastic. Have you used Boo? Amazing stuff.... DSLs are the future in a big way I believe which we already see in Linq providers.

Miron il

Thursday, November 27, 2008 8:26 AM

Miron

@Demon,
What up with you man? Are you a philosopher ?
What are you talking about ?

Damon Wilder Carr us

Monday, December 08, 2008 1:57 AM

Damon Wilder Carr

Miron,

Actually.. If I had another job that would be it.. But no I'm just a coder like you. I've been burned so many times by premature optimization and managing complexity injected for no good reason (which is most of what we end up doing as coders).

Like I said, it's a good post, but I constantly am leading teams and having to explain why it makes no sense to optimize first.

Damon

Greg us

Wednesday, December 17, 2008 5:22 AM

Greg

Silly question here:
using your great example, how could I pass params object[] args to an expecting constructor?
Could I be approaching this wrong if I need to instantiate a class with arguments?

Please advise.

Also, great examples by Miron and Damien.
Thanks

Miron il

Sunday, December 21, 2008 10:08 AM

Miron

@Greg,
I guess it can be done.
Some modifications in the code are needed, of course.
I will be glad to get some benchmarks results for that Smile

cleaning franchises gb

Thursday, May 21, 2009 9:05 PM

cleaning franchises

Hey - nice blog, just looking around some blogengine.net sites, seems a pretty nice platform. I'm currently using Wordpress for a few of my sites but looking to change one of them over to blogengine.net as a trial run. Anything in particular you would recommend about it? Cheers, Matthew

huangqin cn

Wednesday, July 01, 2009 12:12 PM

huangqin

<p><a href="http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG</a><br>" rel="nofollow">www.uggsale.org/">UGG</a><br>
<a href="http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG sale</a><br>
<a href="www.uggsale.org/ugg-classic-cardy-c-2.html UGG Boots</a><br>
<a href="www.uggsale.org/ugg-classic-cardy-c-2.html UGG Boots</a><br>
<a href="www.uggsale.org/...et-c-10.html">Authentic UGG Boots</a><br>
<a href="http://www.uggsale.org/">Genuine UGG Boots</a><br>
<a href="http://www.uggsale.org/">Origianl UGG Boots</a><br>
<a href="www.uggsale.org/...ghtfall-c-4.html">Women's Ugg</a><br>
<a href="www.uggsale.org/...sic-short-c-1.html">Men's Ugg</a><br>
<a href="www.uggsale.org/...ssic-tall-c-3.html">UGG" rel="nofollow">www.uggsale.org/...ssic-tall-c-3.html">UGG Australia</a><br>
<a href="http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG Store</a><br>
<a href="http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG Official Store</a><br>
<a href="http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG Shop</a> <br>
<a href="http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG" rel="nofollow">http://www.uggsale.org/">UGG Online Store</a><br>
<a href="www.uggsale.org/...-slipper-c-25.html">UGG" rel="nofollow">www.uggsale.org/...-slipper-c-25.html">UGG Boots</a><br>
<a href="www.uggsale.org/...1010309-p-995.html">UGG Boot</a><br>
<a href="www.uggsale.org/...sandal-p-1010.html">UGG Sandal</a><br>
<a href="www.uggsale.org/...-sandal-p-991.html">UGG Sandals</a><br>
<a href="www.uggsale.org/...nd-1704-p-998.html">UGG Slipper</a><br>
<a href="www.uggsale.org/...k-5114-p-1031.html">UGG Slippers</a><br>
<a href="www.uggsale.org/...sic-cardy-c-2.html">UGG Classic Cardy</a><br>
<a href="www.uggsale.org/...-crochet-c-10.html">UGG Classic Crochet</a><br>
<a href="www.uggsale.org/...ssic-mini-c-6.html">UGG Classic Mini</a><br>
<a href="www.uggsale.org/...sic-short-c-1.html">UGG Classic Short</a><br>
<a href="www.uggsale.org/...ssic-tall-c-3.html">UGG" rel="nofollow">www.uggsale.org/...ssic-tall-c-3.html">UGG Classic Tall</a><br>
<a href="www.uggsale.org/...nightfall-c-4.html">UGG Nightfall</a><br>
<a href="www.uggsale.org/...tra-short-c-7.html">UGG Ultra Short</a><br>
<a href="www.uggsale.org/...ltra-tall-c-8.html">UGG Ultra Tall</a><br>
<a href="www.uggsale.org/ugg-tasmina-c-11.html">UGG Tasmina</a><br>
<a href="www.uggsale.org/...ie-suede-c-19.html">UGG Amelie Suede</a><br>
<a href="www.uggsale.org/...y-sandal-c-18.html">UGG Gypsy Sandal</a><br>
<a href="www.uggsale.org/...a-sandal-c-22.html">Ugg Matala Sandal</a><br>
<a href="www.uggsale.org/...i-sandal-c-17.html">UGG Halendi Sandal</a><br>
<a href="www.uggsale.org/...-slipper-c-20.html">UGG Hammond Slipper</a><br>
<a href="www.uggsale.org/...-slipper-c-25.html">UGG" rel="nofollow">www.uggsale.org/...-slipper-c-25.html">UGG Layback Slipper</a><br>
<a href="www.uggsale.org/...e-sandal-c-21.html">Ugg Napoule Sandal</a><br>
<a href="www.uggsale.org/...e-sandal-c-24.html">Ugg Persephone Sandal</a><br>
<a href="www.uggsale.org/ugg-skimmer-c-23.html">Ugg Skimmer
</a></p>

Add comment


(Will show your Gravatar icon)  

  Country flag





Live preview

Friday, July 03, 2009 5:36 PM