Create object instances Faster than Reflection

Object Create Benchmark Test ResultEverybody knows that Reflection is a really very important topic in .NET. So I won't repeat the importance of it, it is an unquestionable subject; besides, I have to admit that it saved my life too many times. 

But like every good thing Reflection has also some disadvantages, too. One of the important disadvantages of the Reflection is performance. 

Actually, if we talk about considering a few reflection operations, there won't be any performance problem because Reflection is not slow. It is just slower than the other ways which make us do the same operations. For example:
// WAY 1 normal instance creation
ArrayList list = new ArrayList();

// WAY 2 Using reflection to create an instance of a type
ArrayList list = (ArrayList)typeof(ArrayList).GetConstructor(Type.EmptyTypes).Invoke(null);

If we call the methods above not too many times at the same time, there won't be any performance problem but there might be a performance problem if we call this reflection example too many times in any iteration as for, while, foreach etc. For example:

Stopwatch watch = new Stopwatch();
Type t = typeof(ArrayList);
ConstructorInfo info = t.GetConstructor(Type.EmptyTypes);

object o = null;
ArrayList list = null;
watch.Start();
for (int i = 0; i < 1000000; i++)
{
    list = new ArrayList();
}
watch.Stop();
Console.WriteLine(string.Format("new : {0} ms", watch.ElapsedMilliseconds));

GC.Collect();

o = null;
watch.Start();
for (int i = 0; i < 1000000; i++)
{
    o = info.Invoke(null);
}
watch.Stop();
Console.WriteLine(string.Format("Reflection : {0} ms", watch.ElapsedMilliseconds));
When you run the code above, the output will be as follows:
new : 23 ms
Reflection : 1131 ms


As you see in the previous example, if you use Reflection to create too many items, it will work very slowly. To we talk about the first method (using new), we can only use it when we know the object's Type during the coding time. Otherwise, we cannot use the new keyword to create an instance of an unknown type. In the world of programming, this is a very common situation because we usually don't know the actual type during the coding, so we have to use Reflection in scenarios like this to create instances of a Type.

There are two different ways to make this code run faster. One of them is using Activator class to create object instances from Types. If we want to use the Activator class in the example above to create an instance of an object, the code will be as runs:
o = null;
watch.Start();
for (int i = 0; i < 1000000; i++)
{
   o = Activator.CreateInstance(t);
}
watch.Stop();
Console.WriteLine(string.Format("Activator : {0} ms", watch.ElapsedMilliseconds));

If we execute this code, we'll get the following result:

Activator : 207 ms.

However, this is not the best way. Yes, this is fast but there is also another way which run faster than the Activator class.
The last method I mention is using DynamicMethod method. Dynamic method is a method which we instantiate in the runtime in memory, and works as any method we wrote in our programs

/// <summary>
///
Class which creates a dynamic method for the given type
///
</summary>
public class
ObjectCreateMethod
{
    delegate object MethodInvoker
();
    MethodInvoker methodHandler = null
;

    public
ObjectCreateMethod(Type type)
    {
        CreateMethod(type.GetConstructor(Type
.EmptyTypes));
    }

    public
ObjectCreateMethod(ConstructorInfo target)
    {
        CreateMethod(target);
    }

    void
CreateMethod(ConstructorInfo target)
    {
        DynamicMethod dynamic = new DynamicMethod(string
.Empty,
                    typeof(object
),
                    new Type
[0],
                    target.DeclaringType);
        ILGenerator
il = dynamic.GetILGenerator();
        il.DeclareLocal(target.DeclaringType);
        il.Emit(OpCodes
.Newobj, target);
        il.Emit(OpCodes
.Stloc_0);
        il.Emit(OpCodes
.Ldloc_0);
        il.Emit(OpCodes
.Ret);

        methodHandler = (MethodInvoker)dynamic.CreateDelegate(typeof(MethodInvoker
));
    }

    public
object CreateInstance()
    {
        return
methodHandler();
    }
}

ObjectCreateMethod inv = new ObjectCreateMethod(info);
o = null
;
watch.Start();
for (int
i = 0; i < 1000000; i++)
{
    o = inv.CreateInstance();
}
watch.Stop();
Console.WriteLine(string.Format("Method Invocation : {0} ms", watch.ElapsedMilliseconds));

When we run the code above, the output will be as follows:
Method Invocation : 27 ms.

Here in this example, we are creating an instance of DynamicMethod and fill DynamicMethod's body by using ILGenerator class. And in the IL, we use the Newobj-(Argument: Method Token)- OpCode (which means creating an instance of a Type) to create an instance, and than we return the created object to the caller. This is also what the new keyword does in the IL. So our performance will be as the same as the new keyword's performance. Also to use the DynamicMethod, we used CreateDelegate method of the DynamicMethod, which creates a new delegate which we can use to execute this method. By calling CreateInstance method in the ObjectCreateMethod class, our DynamicMethod is invoked and returns the result.

Finally as you see here, if you use DynamicMethod to create instances of a Type (if you don't know the exact type during coding, otherwise you can use new :) ) is the fastest way to create an instance of the object.

You don't need to write your own Dynamic method creator classes, you can use the ObjectCreateMethod instances in your applications. Of course this method is just for the constructors which has no parameters. If you want to run a constructor which takes parameters, then you have to write your own Dynamic Methods.

See you later ...

Download Test Codes  -  More about Dynamic Methods

Comments

May 23. 2008 04:25 AM

I've noticed that using your sample code, the fastest method is always the one that runs first, and the slowest is always the one that runs last. Try rearranging the order of your methods and see what your benchmark says. I had hand coded my own version of your sample blocks, thus I ended up with the DynamicMethod version last in the list, and it was also the slowest.
wade
May 24. 2008 06:04 PM

Hi Wade,

Actually if you run the Dynamic Methods after the Reflection there will be a lost of performance in the Dynamic methods. So you have to do the tests standalone.

First try to test only new, which will returns 28 ms at my computer.
Second try to test only Reflection, which will returns 1200 ms at my computer.
And finally try to test only Dynamic Method, which will returns 28 ms at my computer.

Using reflection before the dynamic method will make the dynamic methods slow. Why this happens ?? At the moment i dont know exaclty but i will check it also and find why using reflection before dynamic methods cause lost of performance...

Thanks

Ozcan DEGIRMENCI
May 29. 2008 02:54 PM

I think, this article will help you to find the answer of why reflection causes the app. to run slowly: msdn.microsoft.com/en-us/magazine/cc163759.aspx -look at the section "Early-Bound and Late-Bound Invocation"
Also, I came across http://blogs.msdn.com/haibo_luo/default.aspx?p=2

Ada
November 17. 2009 02:56 PM

Hey Ozcan DEGIRMENCI,

Thanks for your informatic post. I just want to know creating Object using Activator class.

ie Activator.CreateObject(Type);

Is it fast than your method?

Sasikumar
November 17. 2009 03:42 PM

Hi Sasikumar,
The post is not only about how we can create objects fater than Reflection but also faster than Activator.CreateInstance. As you can see in the post that time that needs for Dynamic method is 24 ms and time for the activator is 236 ms. So we can surely say that this method is faster than the Activator.

Ozcan DEGIRMENCI
November 17. 2009 04:14 PM

Hi Ozcan DEGIRMENCI,

I tried your method of dynamic method invocation using Delegate. But it throws error some CLR error. invalid operation exception. Please check my code below and correct me.

delegate void GenerateReport(ReportViewer RV, Object Arg);
MethodInfo Method = ReportClass.GetMethod("GenerateReport"); //ReportClass is a Type
if (Method != null)
{
ReportViewer RV = new ReportViewer(null);
Object Args=DeSerializeObject(report.Arguments.ToArray());
DynamicMethod DynMethod = new DynamicMethod(String.Empty, null, new Type[] { typeof(ReportViewer), typeof(Object) },ReportClass,false);
ILGenerator IL = DynMethod.GetILGenerator();
IL.Emit(OpCodes.Call, Method);
GenerateReport GenReport = (GenerateReport)DynMethod.CreateDelegate(typeof(GenerateReport));
GenReport( RV, Args );

Sasikumar
November 17. 2009 05:32 PM

This wont work. Because the IL which you provided seems wront. Frist of all there must be a return at the end of the method. Also I guess that that GenerateReport metod is an instance method, so you need to send the instance to your dynamic method, then Load that argument to the stack then call your GenerateReport metot on that instance.
Ozcan DEGIRMENCI

Search

Calendar

<<  April 2014  >>
MonTueWedThuFriSatSun
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011
View posts in large calendar

Disclaimer

© 2007 - 2011
Ozcan DEGIRMENCI
All rights reserved. The content can be used elsewhere given that the source is properly acknowledged.