473,386 Members | 1,820 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Delegates vs. MethodInfo When Calling Code Dynamically

I've been led to believe by several articles, particularly Eric Gunnerson's
C# Calling Code Dynamically, that calling a method dynamically through
Reflection was much slower than through a Delegate. My testing showed that
actually it was six times faster: 0.5 seconds for 100,000 iterations versus
3.1 seconds.

Can anyone explain why? Something in the way I coded it? I'd appreciate
any insights.

Here's the code (in a Windows Form with two buttons). Operating system is
Windows XP Pro. Visual Studio 2005. .Net Framework 2.0.

const string OP_GREATER_THAN_OR_EQUAL = "op_GreaterThanOrEqual";
const string OP_LESS_THAN_OR_EQUAL = "op_LessThanOrEqual";
const decimal TEST_VAL = 100000.00M;
const decimal BENCHMARK_VAL = 101000.00M;
const int TEST_LIMIT = 100000;

private delegate bool OperatorTest( decimal pTestVal, decimal pBenchmarkVal );

private void btnMethodInfo_Click( object sender, EventArgs e ){
DateTime start = DateTime.Now;
for( int i = 0; i < TEST_LIMIT; i++ )
{
Type t1 = TEST_VAL.GetType();
Type t2 = BENCHMARK_VAL.GetType();
MethodInfo mi = typeof( decimal ).GetMethod(
OP_GREATER_THAN_OR_EQUAL, new Type[] { t1, t2 } );
bool isValid = ( bool )mi.Invoke( null, new object[] { TEST_VAL,
BENCHMARK_VAL } );
}
DateTime stop = DateTime.Now;
Console.WriteLine( "Elapsed time by MethodInfo = " + ( stop- start ) );
}

private void btnDelegate_Click( object sender, EventArgs e ){
DateTime start = DateTime.Now;
for( int i = 0; i < TEST_LIMIT; i++ )
{
Delegate d = Delegate.CreateDelegate( typeof( OperatorTest ), typeof(
decimal ), OP_GREATER_THAN_OR_EQUAL );
bool isValid = ( bool )d.DynamicInvoke( new object[] { TEST_VAL,
BENCHMARK_VAL } );
}
DateTime stop = DateTime.Now;
Console.WriteLine( "Elapsed time by Delegate = " + ( stop - start ) );
}

--
Tom Corcoran
Nov 9 '07 #1
15 8163
I think you need to go back and revisit your code. Your delegate is being
created multiple times inside the loop, and this is eating up CPU cycles.
Only need to create the delegate one time. Haven't looked further, but there
could be other gotchas too.
-- Peter
http://www.eggheadcafe.com
unBlog: http://petesbloggerama.blogspot.com
BlogMetaFinder: http://www.blogmetafinder.com

"Tom Corcoran" wrote:
I've been led to believe by several articles, particularly Eric Gunnerson's
C# Calling Code Dynamically, that calling a method dynamically through
Reflection was much slower than through a Delegate. My testing showed that
actually it was six times faster: 0.5 seconds for 100,000 iterations versus
3.1 seconds.

Can anyone explain why? Something in the way I coded it? I'd appreciate
any insights.

Here's the code (in a Windows Form with two buttons). Operating system is
Windows XP Pro. Visual Studio 2005. .Net Framework 2.0.

const string OP_GREATER_THAN_OR_EQUAL = "op_GreaterThanOrEqual";
const string OP_LESS_THAN_OR_EQUAL = "op_LessThanOrEqual";
const decimal TEST_VAL = 100000.00M;
const decimal BENCHMARK_VAL = 101000.00M;
const int TEST_LIMIT = 100000;

private delegate bool OperatorTest( decimal pTestVal, decimal pBenchmarkVal );

private void btnMethodInfo_Click( object sender, EventArgs e ){
DateTime start = DateTime.Now;
for( int i = 0; i < TEST_LIMIT; i++ )
{
Type t1 = TEST_VAL.GetType();
Type t2 = BENCHMARK_VAL.GetType();
MethodInfo mi = typeof( decimal ).GetMethod(
OP_GREATER_THAN_OR_EQUAL, new Type[] { t1, t2 } );
bool isValid = ( bool )mi.Invoke( null, new object[] { TEST_VAL,
BENCHMARK_VAL } );
}
DateTime stop = DateTime.Now;
Console.WriteLine( "Elapsed time by MethodInfo = " + ( stop- start ) );
}

private void btnDelegate_Click( object sender, EventArgs e ){
DateTime start = DateTime.Now;
for( int i = 0; i < TEST_LIMIT; i++ )
{
Delegate d = Delegate.CreateDelegate( typeof( OperatorTest ), typeof(
decimal ), OP_GREATER_THAN_OR_EQUAL );
bool isValid = ( bool )d.DynamicInvoke( new object[] { TEST_VAL,
BENCHMARK_VAL } );
}
DateTime stop = DateTime.Now;
Console.WriteLine( "Elapsed time by Delegate = " + ( stop - start ) );
}

--
Tom Corcoran
Nov 9 '07 #2
I see a few other things going on here.

First, you (the OP) should be using the Stopwatch class in the
System.Diagnostics namespace to perform the timing. It will provide a much
more accurate result than the DateTime class.

Regarding the loop that calls through reflection, every iteration
through the loop is getting the decimal type three times, and then getting
the method, and then calling the method. You want to test just calling the
method, not all those other things. To that end, the code in that event
handler should look like this:

private void btnMethodInfo_Click( object sender, EventArgs e )
{
// The stopwatch instance.
Stopwatch sw = new Stopwatch();

// Get the type of decimal.
Type decimalType = typeof(decimal);

// Get the method info.
MethodInfo mi = decimalType.GetMethod(OP_GREATER_THAN_OR_EQUAL, new Type[]
{ decimalType, decimalType });

// NOW start the timer.
sw.Start();

// Iterate.
for( int i = 0; i < TEST_LIMIT; i++ )
{
// Invoke the method.
bool isValid = (bool) mi.Invoke(null, new object[] { TEST_VAL,
BENCHMARK_VAL } );
}

// Stop the timer.
sw.Stop();

// Write the result.
Console.WriteLine( "Elapsed time by MethodInfo = " + sw.Elapsed );
}

Regarding the loop that calls through the delegate, most of what applies
in the other method applies here. You only need to create the delegate
once, the types once, etc, etc:

private void btnDelegate_Click( object sender, EventArgs e )
{
// The stopwatch instance.
Stopwatch sw = new Stopwatch();

// Get the delegate.
Delegate d = Delegate.CreateDelegate(typeof(OperatorTest), typeof(decimal),
OP_GREATER_THAN_OR_EQUAL);

// NOW start the timer.
sw.Start();

// Iterate.
for( int i = 0; i < TEST_LIMIT; i++ )
{
// Invoke the delegate.
bool isValid = (bool) d.DynamicInvoke(new object[] { TEST_VAL,
BENCHMARK_VAL } );
}

// Stop the stopwatch.
sw.Stop();

// Output the result.
Console.WriteLine("Elapsed time by Delegate = " + sw.Elapsed);
}

I think that doing it this way will produce very different (and
expected) results for the OP.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Peter Bromberg [C# MVP]" <pb*******@yahoo.NoSpamMaam.comwrote in message
news:AF**********************************@microsof t.com...
>I think you need to go back and revisit your code. Your delegate is being
created multiple times inside the loop, and this is eating up CPU cycles.
Only need to create the delegate one time. Haven't looked further, but
there
could be other gotchas too.
-- Peter
http://www.eggheadcafe.com
unBlog: http://petesbloggerama.blogspot.com
BlogMetaFinder: http://www.blogmetafinder.com

"Tom Corcoran" wrote:
>I've been led to believe by several articles, particularly Eric
Gunnerson's
C# Calling Code Dynamically, that calling a method dynamically through
Reflection was much slower than through a Delegate. My testing showed
that
actually it was six times faster: 0.5 seconds for 100,000 iterations
versus
3.1 seconds.

Can anyone explain why? Something in the way I coded it? I'd appreciate
any insights.

Here's the code (in a Windows Form with two buttons). Operating system
is
Windows XP Pro. Visual Studio 2005. .Net Framework 2.0.

const string OP_GREATER_THAN_OR_EQUAL = "op_GreaterThanOrEqual";
const string OP_LESS_THAN_OR_EQUAL = "op_LessThanOrEqual";
const decimal TEST_VAL = 100000.00M;
const decimal BENCHMARK_VAL = 101000.00M;
const int TEST_LIMIT = 100000;

private delegate bool OperatorTest( decimal pTestVal, decimal
pBenchmarkVal );

private void btnMethodInfo_Click( object sender, EventArgs e ){
DateTime start = DateTime.Now;
for( int i = 0; i < TEST_LIMIT; i++ )
{
Type t1 = TEST_VAL.GetType();
Type t2 = BENCHMARK_VAL.GetType();
MethodInfo mi = typeof( decimal ).GetMethod(
OP_GREATER_THAN_OR_EQUAL, new Type[] { t1, t2 } );
bool isValid = ( bool )mi.Invoke( null, new object[] { TEST_VAL,
BENCHMARK_VAL } );
}
DateTime stop = DateTime.Now;
Console.WriteLine( "Elapsed time by MethodInfo = " + ( stop-
start ) );
}

private void btnDelegate_Click( object sender, EventArgs e ){
DateTime start = DateTime.Now;
for( int i = 0; i < TEST_LIMIT; i++ )
{
Delegate d = Delegate.CreateDelegate( typeof( OperatorTest ),
typeof(
decimal ), OP_GREATER_THAN_OR_EQUAL );
bool isValid = ( bool )d.DynamicInvoke( new object[] { TEST_VAL,
BENCHMARK_VAL } );
}
DateTime stop = DateTime.Now;
Console.WriteLine( "Elapsed time by Delegate = " + ( stop - start ) );
}

--
Tom Corcoran
Nov 10 '07 #3
Nicholas and Peter, thank you both very much. Nicholas, thank you in
particular for taking the time to code a better version and for teaching me
about Stopwatch. Using your code and Stopwatch, the elapsed time of the
Delegates method was still about 3.5 times SLOWER than that of the MethodInfo
method. This seems counter to all that I have heard about Reflection and
Delegates. I'd appreciate any other ideas you might have, as I'm putting a
change into an Xml web service that will likely get a high traffic needing a
dynamically called comparison operator.
--
Tom Corcoran
"Nicholas Paldino [.NET/C# MVP]" wrote:
I see a few other things going on here.

First, you (the OP) should be using the Stopwatch class in the
System.Diagnostics namespace to perform the timing. It will provide a much
more accurate result than the DateTime class.

Regarding the loop that calls through reflection, every iteration
through the loop is getting the decimal type three times, and then getting
the method, and then calling the method. You want to test just calling the
method, not all those other things. To that end, the code in that event
handler should look like this:

private void btnMethodInfo_Click( object sender, EventArgs e )
{
// The stopwatch instance.
Stopwatch sw = new Stopwatch();

// Get the type of decimal.
Type decimalType = typeof(decimal);

// Get the method info.
MethodInfo mi = decimalType.GetMethod(OP_GREATER_THAN_OR_EQUAL, new Type[]
{ decimalType, decimalType });

// NOW start the timer.
sw.Start();

// Iterate.
for( int i = 0; i < TEST_LIMIT; i++ )
{
// Invoke the method.
bool isValid = (bool) mi.Invoke(null, new object[] { TEST_VAL,
BENCHMARK_VAL } );
}

// Stop the timer.
sw.Stop();

// Write the result.
Console.WriteLine( "Elapsed time by MethodInfo = " + sw.Elapsed );
}

Regarding the loop that calls through the delegate, most of what applies
in the other method applies here. You only need to create the delegate
once, the types once, etc, etc:

private void btnDelegate_Click( object sender, EventArgs e )
{
// The stopwatch instance.
Stopwatch sw = new Stopwatch();

// Get the delegate.
Delegate d = Delegate.CreateDelegate(typeof(OperatorTest), typeof(decimal),
OP_GREATER_THAN_OR_EQUAL);

// NOW start the timer.
sw.Start();

// Iterate.
for( int i = 0; i < TEST_LIMIT; i++ )
{
// Invoke the delegate.
bool isValid = (bool) d.DynamicInvoke(new object[] { TEST_VAL,
BENCHMARK_VAL } );
}

// Stop the stopwatch.
sw.Stop();

// Output the result.
Console.WriteLine("Elapsed time by Delegate = " + sw.Elapsed);
}

I think that doing it this way will produce very different (and
expected) results for the OP.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Peter Bromberg [C# MVP]" <pb*******@yahoo.NoSpamMaam.comwrote in message
news:AF**********************************@microsof t.com...
I think you need to go back and revisit your code. Your delegate is being
created multiple times inside the loop, and this is eating up CPU cycles.
Only need to create the delegate one time. Haven't looked further, but
there
could be other gotchas too.
-- Peter
http://www.eggheadcafe.com
unBlog: http://petesbloggerama.blogspot.com
BlogMetaFinder: http://www.blogmetafinder.com

"Tom Corcoran" wrote:
I've been led to believe by several articles, particularly Eric
Gunnerson's
C# Calling Code Dynamically, that calling a method dynamically through
Reflection was much slower than through a Delegate. My testing showed
that
actually it was six times faster: 0.5 seconds for 100,000 iterations
versus
3.1 seconds.

Can anyone explain why? Something in the way I coded it? I'd appreciate
any insights.

Here's the code (in a Windows Form with two buttons). Operating system
is
Windows XP Pro. Visual Studio 2005. .Net Framework 2.0.

const string OP_GREATER_THAN_OR_EQUAL = "op_GreaterThanOrEqual";
const string OP_LESS_THAN_OR_EQUAL = "op_LessThanOrEqual";
const decimal TEST_VAL = 100000.00M;
const decimal BENCHMARK_VAL = 101000.00M;
const int TEST_LIMIT = 100000;

private delegate bool OperatorTest( decimal pTestVal, decimal
pBenchmarkVal );

private void btnMethodInfo_Click( object sender, EventArgs e ){
DateTime start = DateTime.Now;
for( int i = 0; i < TEST_LIMIT; i++ )
{
Type t1 = TEST_VAL.GetType();
Type t2 = BENCHMARK_VAL.GetType();
MethodInfo mi = typeof( decimal ).GetMethod(
OP_GREATER_THAN_OR_EQUAL, new Type[] { t1, t2 } );
bool isValid = ( bool )mi.Invoke( null, new object[] { TEST_VAL,
BENCHMARK_VAL } );
}
DateTime stop = DateTime.Now;
Console.WriteLine( "Elapsed time by MethodInfo = " + ( stop-
start ) );
}

private void btnDelegate_Click( object sender, EventArgs e ){
DateTime start = DateTime.Now;
for( int i = 0; i < TEST_LIMIT; i++ )
{
Delegate d = Delegate.CreateDelegate( typeof( OperatorTest ),
typeof(
decimal ), OP_GREATER_THAN_OR_EQUAL );
bool isValid = ( bool )d.DynamicInvoke( new object[] { TEST_VAL,
BENCHMARK_VAL } );
}
DateTime stop = DateTime.Now;
Console.WriteLine( "Elapsed time by Delegate = " + ( stop - start ) );
}

--
Tom Corcoran
Nov 12 '07 #4
On Nov 12, 1:50 pm, Tom Corcoran
<TomCorco...@discussions.microsoft.comwrote:
Nicholas and Peter, thank you both very much. Nicholas, thank you in
particular for taking the time to code a better version and for teaching me
about Stopwatch. Using your code and Stopwatch, the elapsed time of the
Delegates method was still about 3.5 times SLOWER than that of the MethodInfo
method. This seems counter to all that I have heard about Reflection and
Delegates. I'd appreciate any other ideas you might have, as I'm putting a
change into an Xml web service that will likely get a high traffic needing a
dynamically called comparison operator.
Could you show your new complete code? It would be useful to have a
copy that we can run ourselves. Was your timing performed within the
debugger or not?

Jon

Nov 12 '07 #5
Jon,

Thanks for your reply. Here is the new code as rewritten by Nicholas. The
timing was performed within the debugger.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

namespace DelegatesProblem
{
public partial class Form1 : Form
{
const string OP_GREATER_THAN_OR_EQUAL = "op_GreaterThanOrEqual";
const string OP_LESS_THAN_OR_EQUAL = "op_LessThanOrEqual";
const decimal TEST_VAL = 100000.00M;
const decimal BENCHMARK_VAL = 101000.00M;
const int TEST_LIMIT = 100000;

private delegate bool OperatorTest( decimal pTestVal, decimal
pBenchmarkVal );

public Form1()
{
InitializeComponent();
}

private void btnMethodInfo_Click( object sender, EventArgs e )
{
this.Cursor = Cursors.WaitCursor;
Stopwatch sw = new Stopwatch();
Type decimalType = typeof( decimal );
MethodInfo mi = decimalType.GetMethod(OP_GREATER_THAN_OR_EQUAL,
new Type[]{decimalType, decimalType} );
sw.Start();
for( int i = 0; i < TEST_LIMIT; i++ )
{
bool isValid = ( bool )mi.Invoke( null, new object[] {
TEST_VAL, BENCHMARK_VAL } );
}
sw.Stop();
Console.WriteLine( "Elapsed time by MethodInfo = " + sw.Elapsed );
this.Cursor = Cursors.Default;
}

private void btnDelegate_Click( object sender, EventArgs e )
{
this.Cursor = Cursors.WaitCursor;
Stopwatch sw = new Stopwatch();
Delegate d = Delegate.CreateDelegate( typeof( OperatorTest ),
typeof( decimal ), OP_GREATER_THAN_OR_EQUAL );
sw.Start();
for( int i = 0; i < TEST_LIMIT; i++ )
{
bool isValid = ( bool )d.DynamicInvoke( new object[] {
TEST_VAL, BENCHMARK_VAL } );
}
sw.Stop();
Console.WriteLine( "Elapsed time by Delegate = " + sw.Elapsed );
this.Cursor = Cursors.Default;
}

private void btnDone_Click( object sender, EventArgs e )
{
this.Close();
this.Dispose();
}
}
}
--
Tom Corcoran
"Jon Skeet [C# MVP]" wrote:
On Nov 12, 1:50 pm, Tom Corcoran
<TomCorco...@discussions.microsoft.comwrote:
Nicholas and Peter, thank you both very much. Nicholas, thank you in
particular for taking the time to code a better version and for teaching me
about Stopwatch. Using your code and Stopwatch, the elapsed time of the
Delegates method was still about 3.5 times SLOWER than that of the MethodInfo
method. This seems counter to all that I have heard about Reflection and
Delegates. I'd appreciate any other ideas you might have, as I'm putting a
change into an Xml web service that will likely get a high traffic needing a
dynamically called comparison operator.

Could you show your new complete code? It would be useful to have a
copy that we can run ourselves. Was your timing performed within the
debugger or not?

Jon

Nov 12 '07 #6
On Nov 12, 2:11 pm, Tom Corcoran
<TomCorco...@discussions.microsoft.comwrote:
Thanks for your reply. Here is the new code as rewritten by Nicholas. The
timing was performed within the debugger.
Four things:

1) Code within a Windows Form (or any MarshalByRefComponent) has a few
optimisations disabled.
2) It's easier to compile and run short console apps :)
3) Performance testing in a debugger is a really bad idea
4) Calling DynamicInvoke isn't the same as directly calling the
delegate in a strongly-typed manner

Here's the equivalent code, rewritten as a console app, including a
direct invocation, and with more iterations to give more useful
results:

using System;
using System.Diagnostics;
using System.Reflection;

class Benchmark
{
const string OpGreaterThanOrEqual = "op_GreaterThanOrEqual";

const int Iterations = 1000000;
const decimal FirstValue = 100000.00m;
const decimal SecondValue = 101000.00m;

private delegate bool OperatorTest (decimal first, decimal
second);

static void Main()
{
RunDelegateDynamic();
RunDelegateDirect();
RunReflection();
}

static void RunDelegateDirect()
{
OperatorTest d = (OperatorTest) Delegate.CreateDelegate
(typeof(OperatorTest), typeof(decimal),
OpGreaterThanOrEqual);

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
d(FirstValue, SecondValue);
}
sw.Stop();
Console.WriteLine ("Direct invoke: "+sw.ElapsedMilliseconds);
}

static void RunDelegateDynamic()
{
Delegate d = Delegate.CreateDelegate (typeof(OperatorTest),
typeof(decimal),
OpGreaterThanOrEqual);
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
d.DynamicInvoke(new object[] { FirstValue, SecondValue });
}
sw.Stop();
Console.WriteLine ("Dynamic invoke: "+sw.ElapsedMilliseconds);
}

static void RunReflection()
{
MethodInfo mi =
typeof(decimal).GetMethod(OpGreaterThanOrEqual,
new Type[] {typeof(decimal), typeof(decimal) });
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
mi.Invoke(null, new object[] { FirstValue, SecondValue });
}
sw.Stop();
Console.WriteLine ("Reflection: "+sw.ElapsedMilliseconds);
}
}

Here are the results on my box, not running
Dynamic invoke: 5433
Direct invoke: 82
Reflection: 2048

So yes, calling DynamicInvoke on a delegate is still slower than using
reflection - I suspect it's using reflection under the hood, but with
some extra hoops. However, calling the delegate *directly* (which is
what you should be aiming to do normally) is much, much faster than
reflection.

Jon

Nov 12 '07 #7
Jon,

I got comparable results. Thank you for showing me these things. I know a
bit more about Delegates now and much more about running benchmark tests. I
appreciate your time on it.

Sincerely,
Tom Corcoran
"Jon Skeet [C# MVP]" wrote:
On Nov 12, 2:11 pm, Tom Corcoran
<TomCorco...@discussions.microsoft.comwrote:
Thanks for your reply. Here is the new code as rewritten by Nicholas. The
timing was performed within the debugger.

Four things:

1) Code within a Windows Form (or any MarshalByRefComponent) has a few
optimisations disabled.
2) It's easier to compile and run short console apps :)
3) Performance testing in a debugger is a really bad idea
4) Calling DynamicInvoke isn't the same as directly calling the
delegate in a strongly-typed manner

Here's the equivalent code, rewritten as a console app, including a
direct invocation, and with more iterations to give more useful
results:

using System;
using System.Diagnostics;
using System.Reflection;

class Benchmark
{
const string OpGreaterThanOrEqual = "op_GreaterThanOrEqual";

const int Iterations = 1000000;
const decimal FirstValue = 100000.00m;
const decimal SecondValue = 101000.00m;

private delegate bool OperatorTest (decimal first, decimal
second);

static void Main()
{
RunDelegateDynamic();
RunDelegateDirect();
RunReflection();
}

static void RunDelegateDirect()
{
OperatorTest d = (OperatorTest) Delegate.CreateDelegate
(typeof(OperatorTest), typeof(decimal),
OpGreaterThanOrEqual);

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
d(FirstValue, SecondValue);
}
sw.Stop();
Console.WriteLine ("Direct invoke: "+sw.ElapsedMilliseconds);
}

static void RunDelegateDynamic()
{
Delegate d = Delegate.CreateDelegate (typeof(OperatorTest),
typeof(decimal),
OpGreaterThanOrEqual);
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
d.DynamicInvoke(new object[] { FirstValue, SecondValue });
}
sw.Stop();
Console.WriteLine ("Dynamic invoke: "+sw.ElapsedMilliseconds);
}

static void RunReflection()
{
MethodInfo mi =
typeof(decimal).GetMethod(OpGreaterThanOrEqual,
new Type[] {typeof(decimal), typeof(decimal) });
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
mi.Invoke(null, new object[] { FirstValue, SecondValue });
}
sw.Stop();
Console.WriteLine ("Reflection: "+sw.ElapsedMilliseconds);
}
}

Here are the results on my box, not running
Dynamic invoke: 5433
Direct invoke: 82
Reflection: 2048

So yes, calling DynamicInvoke on a delegate is still slower than using
reflection - I suspect it's using reflection under the hood, but with
some extra hoops. However, calling the delegate *directly* (which is
what you should be aiming to do normally) is much, much faster than
reflection.

Jon

Nov 12 '07 #8
Tom Corcoran <To*********@discussions.microsoft.comwrote:
I got comparable results. Thank you for showing me these things. I know a
bit more about Delegates now and much more about running benchmark tests. I
appreciate your time on it.
No problem. I'm a big fan of small console apps, because you basically
don't need any more code than what you're actually trying to run - no
messing around with buttons, events and the like :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 12 '07 #9
I've seen three ways. MethodInfo and strong type delegate make sense.
In which situation do you need dynamicInvoke

Nov 13 '07 #10
Creativ <Go*********@gmail.comwrote:
I've seen three ways. MethodInfo and strong type delegate make sense.
In which situation do you need dynamicInvoke
When you don't know the type of the delegate at compile-time.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 13 '07 #11
On Nov 13, 9:15 pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
Creativ <GongXinr...@gmail.comwrote:
I've seen three ways. MethodInfo and strong type delegate make sense.
In which situation do you need dynamicInvoke

When you don't know the type of the delegate at compile-time.

--
Jon Skeet - <sk...@pobox.com>http://www.pobox.com/~skeet Blog:http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Can you give me an example? I don't see it. I thought
MethodInfo( reflection) will just do it and faster.

Nov 15 '07 #12
But MethodInfo is a different beast to a Delegate.

I'm not sure it is a good example (I would use typed On{blah} method
myself), but one /potential/ candidate for this would be a
general-purpose event invoke from EventHandlerList...

protected void OnEvent(object key, object sender, EventArgs
args) {
Delegate handler = Events[key];
if (handler != null) {
handler.DynamicInvoke(sender, args);
}
}

Other use-cases might include scenarios such as implementing
ISynchronizeInvoke:

public interface ISynchronizeInvoke {
bool InvokeRequired { get; }
IAsyncResult BeginInvoke(Delegate method, object[] args);
object EndInvoke(IAsyncResult result);
object Invoke(Delegate method, object[] args);
}

I'm not saying that they are common to write, but certainly the latter
gets /used/ very often (think System.Windows.Forms.Control)

Marc
Nov 15 '07 #13
On Nov 15, 8:00 am, Creativ <GongXinr...@gmail.comwrote:
I've seen three ways. MethodInfo and strong type delegate make sense.
In which situation do you need dynamicInvoke
When you don't know the type of the delegate at compile-time.

Can you give me an example? I don't see it. I thought
MethodInfo( reflection) will just do it and faster.
Consider trying to implement ISynchronizeInvoke.Invoke - you're
presented with a Delegate, and an object[]. How are you going to
execute the delegate? I suppose you *could* get the invocation list
and execute it that way, but I suspect that's basically what
DynamicInvoke does under the hood anyway.

Jon
Nov 15 '07 #14
Hello
I've changed some of the values used in your benchmark test(i.e: the delegate type and some of the constants) to match a more realistic situation(upon my opinion...) for the type of function we are trying to execute using invocation and i've obtained different results regarding the difference between the direct invocation and the other 2 types.

Dynamic invoke: 12976
Direct invoke: 12505
Reflection: 13332

Could someone confirm my results and suggest some reason for that?

using System;
using System.Diagnostics;
using System.Reflection;

class Benchmark
{
const string OpGreaterThanOrEqual = "op_GreaterThanOrEqual";

const int Iterations = 100000;//changed
const int V1 = 100000;
const int V2 = 100000;
const decimal FirstValue = 100000.00m;
const decimal SecondValue = 101000.00m;

private delegate bool OperatorTest(decimal first, decimal second);
private delegate void Blah(int first, int second);//added

static void Main()
{
RunDelegateDynamic();
RunDelegateDirect();
RunReflection();
Console.ReadLine();
}

//Some more time consuming function
public static void BlahTst(int first, int second)
{
int res = 0;
for (int i = 0; i < 100000; i++)
{
if (first < second)
{
res = -1;
}
else
{
res = 1;
}
}
}
static void RunDelegateDirect()
{
Blah d = (Blah)Delegate.CreateDelegate(typeof(Blah), (Type)typeof(Benchmark), "BlahTst");

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
d(V1, V2);
}
sw.Stop();
Console.WriteLine("Direct invoke: " + sw.ElapsedMilliseconds);

/*
OperatorTest d = (OperatorTest)Delegate.CreateDelegate
(typeof(OperatorTest), typeof(decimal), OpGreaterThanOrEqual);

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
d(FirstValue, SecondValue);
}
sw.Stop();
Console.WriteLine("Direct invoke: " + sw.ElapsedMilliseconds);
*/
}

static void RunDelegateDynamic()
{
Delegate d = Delegate.CreateDelegate(typeof(Blah), (Type)typeof(Benchmark), "BlahTst");
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
d.DynamicInvoke(new object[] { V1, V2 });
}
sw.Stop();
Console.WriteLine("Dynamic invoke: " + sw.ElapsedMilliseconds);

/*
Delegate d = Delegate.CreateDelegate(typeof(OperatorTest), typeof(decimal), OpGreaterThanOrEqual);
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
d.DynamicInvoke(new object[] { FirstValue, SecondValue });
}
sw.Stop();
Console.WriteLine("Dynamic invoke: " + sw.ElapsedMilliseconds);
*/
}

static void RunReflection()
{
MethodInfo mi = typeof(Benchmark).GetMethod("BlahTst",
new Type[] { typeof(int), typeof(int) });
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
mi.Invoke(null, new object[] { V1, V2 });
}
sw.Stop();
Console.WriteLine("Reflection: " + sw.ElapsedMilliseconds);

/*
MethodInfo mi = typeof(decimal).GetMethod(OpGreaterThanOrEqual,
new Type[] { typeof(decimal), typeof(decimal) });
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
mi.Invoke(null, new object[] { FirstValue, SecondValue });
}
sw.Stop();
Console.WriteLine("Reflection: " + sw.ElapsedMilliseconds);
*/
}
}

Jun 27 '08 #15
On Apr 12, 8:38*pm, Valeriu Lacatusu wrote:
Hello
I've changed some of the values used in your benchmark test(i.e: the delegate type and some of the constants) to match a more realistic situation(uponmy opinion...) for the type of function we are trying to execute using invocation and i've obtained different results regarding the difference between the direct invocation and the other 2 types.

Dynamic invoke: 12976
Direct invoke: 12505
Reflection: 13332

Could someone confirm my results and suggest some reason for that?
Yes - the bulk of the time is now spent within the BlahTst method
itself. Calling the method dynamically doesn't make the method itself
run any slower - it just means the time taken to transfer execution
from the calling method to BlahTst is slower. When that becomes less
significant (because BlahTst is doing more work) you'll see less
difference in the results - as your numbers demonstrate.

Jon
Jun 27 '08 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: LP | last post by:
Hello! I am still transitioning from VB.NET to C#. I undertand the basic concepts of Delegates, more so of Events and somewhat understand AsyncCallback methods. But I need some clarification on...
5
by: cody | last post by:
I have a very funny/strange effect here. if I let the delegate do "return prop.GetGetMethod().Invoke(info.AudioHeader, null);" then I get wrong results, that is, a wrong method is called and I...
3
by: Me | last post by:
I am trying to figure out any issues with calling System.Reflection.MethodInfo.Invoke() when dealing with multiple threads. For instance.. Say I have a class that allows you to pass in a...
12
by: ichor | last post by:
hi i cant seem to understand the difference. can anyone explain or point me to some tutorial that can. thanks
4
by: Cedric Rogers | last post by:
I wasn't sure if I could do this. I believe I am stretching the capability of what generics can do for me but here goes. I have a generic delegate defined as public delegate bool...
0
by: pjr | last post by:
Using VS2005, I dynamically create an event delegate. Code follows question. My method gets the event's parameters and passes them onto a common event handler. My delegate gets called when expected...
1
by: Bruce Wood | last post by:
I'm trying to "genericize" the following class. At the moment I have derived classes for each different type of event handler / event arguments, and I wanted to have a single, generic, catch-all...
6
by: =?Utf-8?B?T2xkQ2FEb2c=?= | last post by:
My question is regarding the use of delegates in C#. I see how .Net uses delegates to wire event handlers to events. It’s an object created by a single line of code by the system and that makes...
7
by: Siegfried Heintze | last post by:
I'm studying the book "Microsoft Visual Basic.NET Language Reference" and I would like some clarify the difference between events and delegates. On page 156 I see a WinForms example of timer that...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.