Pages

Saturday, November 6, 2010

Reflection - Slow or Fast? Demonstration with Solutions

Many of you might have heard, calling reflection APIs from your code is always slower than that of calling it directly.  Well, it is right. Some of the major Reflection methods like GetXXX (of MethodInfo, PropertyInfo, FieldInfo etc) are say 100 times slower than that of calling a Method, Property or Fields directly. In this post, I will try to cover some of the major portion of Reflection which is slower like hell than that of normal method call and also try to solve the same.


So what is Reflection for?

As I have already told you about Reflection and Code Emit and also how to build your Lamda Expression Tree, it is good to know where you would like to use Reflection. Yes... Reflection is made truly late bound approach to browse through the object hierarchy or to call methods inside the object. So if you do not know much about your object hierarchy or you have somehow found an assembly external to your application and you need to parse through the object and call its methods say, then Reflection would be the right choice for you.

So basically Reflection allows you to create plugin type of applications where you define an Interface and publish the same for your application and let others create those plugins for you to seamlessly added to your application. Fine. Then what it isn't for?

Yes basically few people try to work everything based on Reflection. Using reflection unnecessarily will let your application very costly. Say for instance,

ConstructorInfo cinfo= typeof(MyType).GetConstructor(new Type[] { typeof(int), typeof(string) });
object createdObject = cinfo.Invoke(new object[] { 10, "Abhishek" });
MyType xyz = createdObject as MyType;

Or say using
MyType typ = Activator.CreateInstance<MyType>();

Silly huh..
I saw few people to do this. They try to use everything using Reflection, may be they love the Reflection too much, or they have already created a Reflection engine right and do not want to mix up unknown types with known ones. May be they would make their code clear by calling the known types to the same module that is built up for dealing with unknown types.

Download Sample - 60 KB



These things go really worse when you do these reflection calls in a loop.Say for instance, you are about to set 100 of members of an object at runtime and use say PropertyInfo to deal with these 100 setters. Yes, the code will look very simple but at a performance cost.

Type.InvokeMember is often very slow as well as Activator.CreateInstance, when there are large number of Members in a type of there are large number of Types in an assembly. Yes, going truly late bound with these will make your application real slow.

Where should you avoid Reflection ? 

Yes this is the general question for everyone. Reflection works very well when you know the object. The more you know about the object, the more you can avoid going searching the object hierarchy. One of the most costliest method I have found is GetCustomAttributes, where you are trying to find an attribute from a type, whether it is added or not to do something with the types. If you don't know where the Custom attributes to be set to or say you have AttributeTargets.All set to the attribute and you use
 myassembly.GetCustomAttributes(true)

The additional parameter true means it will go through all the Types, its methods, its properties and try to find your attribute. Hence its a call to traverse the whole object hierarchy. Yes, this is horribly costly. You must avoid these calls. Let me list some of the costly methods on Reflection :
  • GetCustomAttributes
  • GetXX ( PropertyInfo, MethodInfo, EventInfo, FieldInfo etc)
  • Type.InvokeMember (when Type is very big)
  • Activator.CreateInstance
There are others too. But you should always try to avoid these methods call in a loop.

Reflection and ASP.NET websites 

When it comes with the notion of ASP.NET websites, we always think of dealing with  performance and throughput. For ASP.NET sites, it is better to avoid excessive usage of Reflection, may be when you use Reflection for every call to invoke a member which is plugged in to your application, it would make your application work slower and slower when you have thousands of calls to your application. This is the problem with DasBlog which actually have used Reflection to deal with each blog posted. Hanselman pointed out the issue for them, as it tries to find out each member using Reflection. The performance of the site increased 100 times just by changing these things.
Yes, if your Web application needs to perform well in stressed condition, I should say you should think twice before using Reflection at your end. Rather it would be lightening fast if you didn't have used Reflection to deal every step.

How slow Reflection is? 

Yes, now its time to deal with Reflection against real time data. As Reflection is truly late bound approach to work with your types, the more Types you have for your single assembly the more slow you go on. Let me try to demonstrate with you how slow the performance is by taking an example of a large dll (with 100s of types associated with it) and try to invoke a member on it using Reflection and without it and measure the performance boost you have.

Eric Gunnerson also employed a lot of effort around measuring the few methods himself. In his article(sorry it isnt available), he demonstrated based on his 100,000 call to a single method in .NET framework 1.1 gives him a result like :



So according to him, Type.InvokeMember and DynamicMethod.Invoke takes the longest time to run. MethodBase.Invoke ( or MethodInfo.Invoke) is half in performance, DynamicMethod.Delege will take even lesser time, next is normal delegate call, finally the interface call and IL based instructions. Fairly smart enough? Probably, but lets build our own application to demonstrate these scenario.

Let me take an example of a simple class,(I call it as DummyClass) which has only 1 method in it named CallMe inside a DummyNamespace on a large assembly with 547 Types.So the class looks like :

namespace DummyNamespace
{
    public class DummyClass
    {
        public void CallMe(int x)
        {
           x = x + 10;
           return;
        }
    }
}


Looks simple huh.. Well, lets create a consumer class to check how it performs in stressed situations. I will create objects of DummyClass in a loop and call CallMe with random values in both using Reflection API and normally. To do this, I create a class ReflectionCalculator with few methods.

public class ReflectionCalculator
{
    private Assembly _currentassembly;
    public Assembly CurrentAssembly
    {
        get
        {
            if (this._currentassembly == null)
                this._currentassembly = Assembly.LoadFrom("PredictADry.BizLogic.dll");
            return this._currentassembly;
        }
    }
    public void ReflectionBasedCall(int value)
    {
        Type dummyclass = this.CurrentAssembly.GetType("DummyNamespace.DummyClass", true, true);
        MethodInfo dummyMethod = dummyclass.GetMethod("CallMe", BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(int) }, null);
        object dummyObject = Activator.CreateInstance(dummyclass);
        dummyMethod.Invoke(dummyObject, new object[] { value });
    }
        
    public void NormalCall(int value)
    {
        DummyClass oclass = new DummyClass();
        oclass.CallMe(value);

    }
}

So if you look into these two calls, viz ReflectionBasedCall and NormalCall, you could see, definitely both are doing the same thing. I have placed a Assembly object outside so that I could check only the logic to call a method. The Reflection approach needs to first Get a Type using Assembly.GetType, which eventually searches the entire object hierarchy and then GetMethod, which finds on the Type. Hence the bigger the size of the assembly, the slower these work. Finally the Activator.CreateInstance which actually creates the instance of the object. While the other is doing the same thing normally. Now if say I call both the methods 100000 times using this code and print out the time in milliseconds, it will look like :

static void Main(string[] args)
{
    DateTime currentTime;
    ReflectionCalculator calculator = new ReflectionCalculator();
    Console.WriteLine("Time Now : {0}", DateTime.Now.ToLocalTime());
    currentTime = DateTime.Now;

    for (int i = 0; i < 100000; i++)
    {
        calculator.NormalCall(i);
    }

    TimeSpan spannedtime = DateTime.Now.Subtract(currentTime);
    Console.WriteLine("Time Elapsed for Normal call : {0}", spannedtime.TotalMilliseconds);

    currentTime = DateTime.Now;
    for (int i = 0; i < 100000; i++)
    {
        calculator.ReflectionBasedCall(i);
    }
    spannedtime = DateTime.Now.Subtract(currentTime);
    Console.WriteLine("Time Elapsed for Reflection call : {0}", spannedtime.TotalMilliseconds);

    Console.ReadLine();
}

Hence the output will be :


So you can definitely get the idea how slow Reflection works in comparison to normal calls. Reflection approach is almost 30 times slower than that of normal call.

Caching Objects to Relax this a bit

Well, lets make the code more friendly to allow catching of objects for each call. So lets create a few properties to cache the objects for Reflection call and see how it works :

private Type dummyType;
public Type DummyType
{
    get 
    { 
        this.dummyType = this.dummyType ?? this.CurrentAssembly.GetType("DummyNamespace.DummyClass", true, true); 
        return this.dummyType; 
    }
}
private MethodInfo method;
public MethodInfo Method
{
    get
    {
        this.method = this.method ?? this.DummyType.GetMethod("CallMe", BindingFlags.Instance | 
                        BindingFlags.Public, null, new Type[] { typeof(int) }, null);
        return this.method;
    }
}
private object dummyObject;
public object DummyObject
{
    get
    {
        if (this.dummyObject == null)
        {
            dummyObject = Activator.CreateInstance(this.DummyType);
        }
        return dummyObject;
    }
}
//More relaxed with caching of objects
public void ReflectionBasedCall(int value)
{
    this.Method.Invoke(this.DummyObject, new object[] { value });
}
public DummyClass MyClass { get; set; }
public void NormalCall(int value)
{
    this.MyClass = this.MyClass ?? new DummyClass();
    this.MyClass.CallMe(20);

}

So here, we cache each objects in its respective properties. So, it might relax our head a bit, but mind that, this could not be the situation of you that you can the same method every time. But to see how fast method Invoke works lets run the code.


So the time consumed abruptly decreased due to caching applied on it. So basically most of the time was taken by GetType and GetMethod and even with Activator.CreateInstance. But if you see the result it is still 15 times the normal call.

Using an Interface

Interface works great in these situations. Lets take an Interface which is present in both the dlls where the DummyClass actually implements the interface IDummy. OMG, interface works so well in these situations. If you have everything cached, it works the same like normal calling instructions.

private IDummy dummyObject;
public IDummy DummyObject
{
    get
    {
        if (this.dummyObject == null)
        {
            dummyObject = Activator.CreateInstance(this.DummyType) as IDummy;
        }
        return dummyObject;
    }
}
public void ReflectionBasedCall(int value)
{
    //this.Method.Invoke(this.DummyObject, new object[] { value });
    this.DummyObject.CallMe(value);
}

Hence the output is :
You must be amazed to see this. Yes, it actually works better in this situation that of normal IL instructions.

But no.. Its actually not. Basically calling a light weight interface is better than calling a concrete object from architectural point of view. If you make the caching of IDummy for a moment and compare you will see the difference. Holding Cached object and calling through its interface is better in performance than that of the normal calls. So lets change our code a bit and see :
private IDummy dummyObject;
public IDummy DummyObject
{
    get
    {
       
        dummyObject = Activator.CreateInstance(this.DummyType) as IDummy;
        return dummyObject;
    }
}
public void ReflectionBasedCall(int value)
{
    this.DummyObject.CallMe(value);
}
public DummyClass MyClass { get; set; }
public void NormalCall(int value)
{
    this.MyClass =  new DummyClass();
    this.MyClass.CallMe(20);

}

Hence if you create both objects each time, the performance will be :



Yes rightly so, Interface will not work better than raw IL instructions. But is it possible to have Interface for everything we call? You are right, it would put a lot of effort if you need to have interface for every single Reflection call. So probably its time to think something else.

Lets use Dynamic Delegates

Well another or probably best approach I found is the use of dynamically created delegates based on signature of MethodInfo, PropertyInfo objects. Using Dynamic flexibility of C# language or creating dynamic delegate at runtime will make the Reflection code very fast.

Basically the idea is to build Generic delegates for each type of MethodInfo we need to call and eventually store the same into some in memory cache.  This way, you just need to build some Action or Func delegates for your calls (based on the signature) and on every call to them, you can maintain a list where you store each delegate with the MethodInfo. Hence for the next time, when you require to invoke the same Method, you could use the delegate directly.

To do this, I have used System.Linq.Expressions. If you are new to Dynamic feature using Expression Tree, you can try my post to grab the concept. I have used Expression as it seems better for me, but you could also use System.Reflection.Emit to build these call wrappers.

To use this, I have created a few extension methods for properties, methods etc. Lets take the example of MethodInfo in our case.

public static Action<object, T> CallMethod<T>(this MethodInfo methodInfo)
{
    if (!methodInfo.IsPublic) return null;

    ParameterExpression returnParameter = Expression.Parameter(typeof(object), "method");
    ParameterExpression valueArgument = Expression.Parameter(typeof(T), "argument");

    MethodCallExpression setterCall = Expression.Call(
                                    Expression.ConvertChecked(returnParameter, methodInfo.DeclaringType),
                                    methodInfo,
                                    Expression.Convert(valueArgument, typeof(T)));
    return Expression.Lambda<Action<object, T>>(setterCall, returnParameter, valueArgument).Compile();
}
So eventually I am using this Lambda expression to build an Action<object,T> where object represents the instance of the class for which we are going to execute the method and T represents the Type argument in the argument list.

If you see the code above cautiously, you could understand that I am building a lambda like :

(x, y) => return x.[method](y)

So using the Caching as well here, lets dynamically build our delegate object using the code:


# region Cache
private MethodInfo methodInfo;
public MethodInfo CachedMethodInfo
{
    get
    {
        this.methodInfo = this.methodInfo ?? this.GetMethodInfo();
        return this.methodInfo;
    }
}

private MethodInfo GetMethodInfo()
{
    Type dummyclass = this.CurrentAssembly.GetType("DummyNamespace.DummyClass", true, true);
    MethodInfo dummyMethod = dummyclass.GetMethod("CallMe", BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(int) }, null);

    return dummyMethod;
}
private object instance;
public object Instance
{
    get
    {
        this.instance = this.instance ?? Activator.CreateInstance(typeof(DummyClass));
        return this.instance;
    }
}
private Action<object, int> _methodcallDelegate = null;
public Action<object, int> MethodCallDelegate
{
    get
    {
        this._methodcallDelegate = this._methodcallDelegate ?? this.CachedMethodInfo.CallMethod<int>();

        return this._methodcallDelegate;
    }
}

# endregion



public void CacheBasedDelegateCall(int value)
{
    this.MethodCallDelegate(this.Instance, value);
}

So basically, I have build an delegate object with MethodCallDelegate and also cached the same for every call of the method.  The MethodCallDelegate actually invokes the extension method CallMethod from CachedMethodInfo object and stores it into a variable.


Note : In your real time application, when you require to create a large number of Reflection calls, cache MethodDelegate in a collection with MethodInfo objects, so that you could try to find the same from the collection instead of creating the Dynamic method each time you call.

Now to demonstrate this lets put another section in our program to call this CacheBasedDelegateCall. Hence the output will look like :


OMG, it works great with this approach. Yes, if you can leverage out the time taken to dynamically compile the application, then the application will work as fast as before.


Download Sample - 60 KB

For Reference 
Common Performance Pitfalls
Transcript of Hanselman speaking on Reflection

Thats it.

Conclusion


If not bored about my tests, I think you have found this interesting and will help you to improve your performance over reflection in your own applications.


Do post feedback if you have anything else. Thank you for reading.

5 comments:

  1. what kind of article is this and what does it bring out. Do we need to really think is reflection faster....Its is slower damn it.Do not write huge articles and waste time..

    ReplyDelete
  2. @Anonymous

    Did you read the whole article ?

    I have clearly showed how I made it faster than before. I think you didnt read the article and just gone through a glance.

    I would recommend you to read the article and then comment. Yes Reflection is slow and using few approaches we can make it faster.

    Thanks.

    ReplyDelete
  3. Hi,

    Tip #1: Activator.CreateInstance calls ctor.Invoke inside. If you want to speed up your application do use ctor.Invoke.

    Tip #2: Try to use Delegate.CreateDelegate and to check execution time.

    ReplyDelete
  4. @osmirnov

    Thank you for your tip. I will try to use Delegate.CreateDelegate to check execution time and update.

    ReplyDelete
  5. Check out Fasterflect (fasterflect.codeplex.com) for a library that uses IL generation and delegate caching to make reflection both easier and more powerful.

    ReplyDelete

Please make sure that the question you ask is somehow related to the post you choose. Otherwise you post your general question in Forum section.