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.

Comments

# cvega said:

Thanks for the tests.

I actually wanted to do a test regarding speed difference but can't find the time to do it, so I just took up a quick response based from what I've read from documentation.

Cheers :)

-chris

Monday, February 16, 2009 5:35 PM
# jakelite said:

No problem sir. The Invoke syntax looked too late-bound for me so I had to investigate further.

Monday, February 16, 2009 7:52 PM
# St Louis Rams said:

great post - thanks for the info!

Thursday, February 19, 2009 6:39 PM