One friend of mine sent me the following code sample that really surprised me.
There are three different approaches being used to call a method from a different class. The approaches are -
- Direct Call
- Call through Lambda based reflection
- Call through Normal Reflection
It was really surprising to see the execution speed comparison between three different approaches. The lambda based approach was found to be the fastest by the order of 1000 times.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
| using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
namespace LambdaReflection
{
class MyClass
{
public void CallIt()
{
}
}
class Program
{
delegate void LocalDel<t>(T mc);
static void Main(string[] args)
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
MethodInfo minfo = typeof(MyClass).GetMethod("CallIt", BindingFlags.Instance | BindingFlags.Public);
MyClass obj = new MyClass();
//compile expression tree
LocalDel<myclass> lambdaExpression = FuncCallIt<myclass>("CallIt");
sw.Reset();
sw.Start();
//Direct call by using object
for (int a = 0; a < 10000; a++)
{
obj.CallIt();
}
sw.Stop();
Console.WriteLine(string.Format("Time taken by Direct call {0}", sw.ElapsedTicks));
sw.Reset();
sw.Start();
//dynamically compiled lambda call
for (int a = 0; a < 10000; a++)
{
lambdaExpression(obj);
}
sw.Stop();
Console.WriteLine(string.Format("Time taken by lambda-expression compilation {0}", sw.ElapsedTicks));
sw.Reset();
sw.Start();
//reflection call
for (int a = 0; a < 10000; a++)
{
minfo.Invoke(obj, null);
}
sw.Stop();
Console.WriteLine(string.Format("Time taken by Reflection call {0}", sw.ElapsedTicks));
Console.ReadLine();
}
private static LocalDel<t> FuncCallIt<t>(string MethodName)
{
var target = Expression.Parameter(typeof(T), "a");
MethodInfo minfo = typeof(T).GetMethod(MethodName, BindingFlags.Instance | BindingFlags.Public);
var methodinvokeExpression = Expression.Call(target, minfo);
var lambda = Expression.Lambda<localdel><t>>(methodinvokeExpression, new ParameterExpression[] { target });
return lambda.Compile();
}
}
} |
Following is the result of the execution on my system:
Time taken by Direct call 2384625
Time taken by lambda-expression compilation 902430
Time taken by Reflection call 518534265
I didn’t expect lambda based call to be faster than direct call but I need to explore as how best I can make use of this knowledge in my real programming scenarios. The compiled lambda demands different compiled lambda expressions for each method being used. However, if performance is the prime objective in the application then I think this tangential approach is worth considering.
What is your opinion on it ?
Recent Comments