MethodInfo.Invoke vs MethodCall Performance on DynamicMethods
I posted a
question
on cvega’s article on using CIL getters and setters to speed up the execution
of heavily reflection-based code asking which one will perform better using
DynamicMethod.Invoke or using DynamicMethod.CreateDelegate then calling that
delegate. On which he promptly replied. But I tonight is one of those nights where I can't get myself to sleep so I
decided to satisfy my curiosity on this matter.
So I
immediately opened my trusty VS.Net IDE and started working on it. The
following are the steps I made to come up with the benchmark results.
I declared
two generic delegates:
delegate P GetPropertyDelegate<O, P>(O objectInstance);
delegate void SetPropertyDelegate<O, P>(O objectInstance, P propertyValue);
I didn't
want to change his existing methods so I decided to add some of my own to the existing classes. They are shown below:
1 //ADDED to PropertyGetter
2 public static P GetPropertyGeneric<O, P>(
3 O instance, string propertyName)
4 {
5 GetPropertyDelegate<O, P> getDelegate =
6 (GetPropertyDelegate<O, P>)
7 GetPropertyGetterMethod(instance, propertyName).
8 CreateDelegate(typeof(GetPropertyDelegate<O, P>));
9 return getDelegate(instance);
10 }
1 //ADDED TO PropertySetter
2 public static void SetPropertyGeneric<O, P>(
3 O instance, string propertyName, P propertyValue)
4 {
5 SetPropertyDelegate<O, P> setDelegate =
6 (SetPropertyDelegate<O, P>)
7 GetPropertySetterMethod(instance, propertyName).
8 CreateDelegate(typeof(SetPropertyDelegate<O, P>));
9 setDelegate(instance, propertyValue);
10 }
For the purpose of illustration, I created a
class called MyClass which has one string Property MyProperty.
1 public class MyClass
2 {
3 private string myVar;
4
5 public string MyProperty
6 {
7 get { return myVar; }
8 set { myVar = value; }
9 }
10 }
Then used
the following code in my main method.
1 MyClass c = new MyClass();
2
3 //make sure the creation of the methods
4 //does not get computed as part of benchmark
5 PropertySetter.SetPropertyValue(c,
6 "MyProperty", "OMGWTFBBQ!!!!");
7 string q = PropertyGetter.GetPropertyValue(c,
8 "MyProperty").ToString();
9
10 int limit = 1024 * 1024 * 2;
11 Stopwatch sw = new Stopwatch();
12
13 Console.Write("GetProperty: ");
14 sw.Start();
15 for (int i = 0; i < limit; i++)
16 {
17 string s = PropertyGetter.GetPropertyValue(c,
18 "MyProperty").ToString();
19 }
20 sw.Stop();
21 Console.WriteLine(sw.Elapsed);
22
23 sw.Reset();
24 Console.Write("GetPropertyGeneric: ");
25 sw.Start();
26 for (int i = 0; i < limit; i++)
27 {
28 string s = PropertyGetter.
29 GetPropertyGeneric<MyClass, string>
30 (c, "MyProperty");
31 }
32 sw.Stop();
33 Console.WriteLine(sw.Elapsed);
34
35 sw.Reset();
36 Console.Write("SetProperty: ");
37 sw.Start();
38 for (int i = 0; i < limit; i++)
39 {
40 PropertySetter.SetPropertyValue
41 (c, "MyProperty", "OMGBBQFTW!!!");
42 }
43 sw.Stop();
44 Console.WriteLine(sw.Elapsed);
45
46
47 sw.Reset();
48 Console.Write("SetPropertyGeneric: ");
49 sw.Start();
50 for (int i = 0; i < limit; i++)
51 {
52 PropertySetter.
53 SetPropertyGeneric<MyClass, string>
54 (c, "MyProperty", "OMGBBQFTW!!!");
55 }
56 sw.Stop();
57 Console.WriteLine(sw.Elapsed);
58
59 Console.ReadKey(false);
Conclusion
The following is the result of executing the program.

As it turns
out CreateDelegate executes faster than Invoke. I think the reason is that the
Invoke call results in something like a MethodInfo.Invoke while the delegate
call is more analogous to an actual method call.
Of course the performance difference is negligible in scenarios which does not require calling the DynamicMethod 1024*1024*2 times in one go. This article is just meant to satisfy the curiosity of a man who finds it difficult to sleep at night. Sources can be downloaded from here.