While studying reflection and delegates, I stumbled upon the first example of this Jon Skeet's post.
While Reflection is notorious for being slow, especially for repeated invocations, I do not really understand how "wrapping" the reflected method into a Delegate can help in avoiding its high computational cost, like suggested in that post first example:
MethodInfo method = typeof(string).GetMethod("IndexOf", new Type[] { typeof(char) });
Func<char, int> converted = (Func<char, int>)
Delegate.CreateDelegate(typeof(Func<char, int>), str, method);
So I've built a short comparision test for myself based on that example. I'm trying to compare different calls to string's IndexOf
method: A) Direct; B) Using reflection; C) Using a delegate.
/*
Based on
https://codeblog.jonskeet.uk/2008/08/09/making-reflection-fly-and-exploring-delegates/
*/
public class Test
{
public static void Main()
{
// Testing the performance of different calls to string method "IndexOf"
string str = "Hello World";
Stopwatch s = new Stopwatch();
float elapsed = 0;
int iterations = 10000000;
//---------
// A) Direct
//---------
for (int i = 0; i < iterations; i++)
{
// Average to reduce noise error
s.Start();
str.IndexOf('H');
s.Stop();
elapsed += s.Elapsed.Ticks;
s.Reset();
}
Console.WriteLine("A) Direct: " + (elapsed / iterations).ToString());
//---------
// B) Reflection
//---------
MethodInfo method = typeof(string).GetMethod("IndexOf", new Type[] { typeof(char) });
for (int i = 0; i < iterations; i++)
{
// Average to reduce noise error
s.Start();
method.Invoke(str, new object[] { 'H' });
s.Stop();
elapsed += s.Elapsed.Ticks;
s.Reset();
}
Console.WriteLine("B) Reflection: " + (elapsed / iterations).ToString());
//---------
// C) Delegate
//---------
Func<char, int> converted = (Func<char, int>)
Delegate.CreateDelegate(typeof(Func<char, int>), str, method);
for (int i = 0; i < iterations; i++)
{
// Average to reduce noise error
s.Start();
converted('H');
s.Stop();
elapsed += s.Elapsed.Ticks;
s.Reset();
}
Console.WriteLine("C) Delegate: " + (elapsed / iterations).ToString());
}
}
On my machine, a typical run would return the following:
A) Direct: 0.3110177
B) Reflection: 3.13324
C) Delegate: 3.154247
Having read that blog post, I was expecting that kind of difference between A) and B); however, I do not understand why I don't get any improvement between B) and C).
Questions
1) Is my testing/measurement strategy correct for this purpose?
1a) If yes, why I am not getting a good difference between B) and C)?
2) I would like an in-depth explanation of why using the delegate form C) should be faster than B). What is happening behind the curtains?
Additional notes
When answering, especially question 2), consider that I am kind of a beginner in both reflection and delegates. Please try to be exhaustive but understandable.
I have done my research on other Stackoverflow questions pivoting around these topics: Performance of reflection method call vs delegate call; What is the "cost" of .NET reflection?; How costly is .NET reflection?
However, none of them was enough for me to get my head around the example above.
Aucun commentaire:
Enregistrer un commentaire