correction - not stack delegate always heap its a ref type. Looks like they intended to have 2 delegate types ( and the single cast one was going to be a struct .)
http://blogs.msdn.com/b/brada/archive/2004/02/05/68415.aspx. Even after create, costs are still good ( especially the lambda) after all we are comparing to a almost no work inlined with polymorph inline cache virt call. Note the create cost only applies via an interface if via an instance method then the cost is minimal. looked into create costs .. ms for 10M calls Interface: 25 Delegate: 26 Delegate with create via interface : 989 Delegate with create : 74 Heap Delegate lambda: 28 Heap Delegate lambda with create : 54 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication2 { public class A { public Func<int, int> del ; } interface IFoo { int Foo(int x); } class Program : IFoo { const int Iterations = 10000000; public int Foo(int x) { return x * 3; } static void Main(string[] args) { var heap = new A(); var heap_lambda = new A(); int x = 3; var prog = new Program(); IFoo ifoo = prog; Func<int, int> del = ifoo.Foo; heap.del = ifoo.Foo; heap_lambda .del = y => y * 3; // force compile ifoo.Foo(3); del(3); heap.del(3); heap_lambda.del(3); Stopwatch sw = Stopwatch.StartNew(); for (int i = 0; i < Iterations; i++) { x = ifoo.Foo(x); } sw.Stop(); Console.WriteLine("Interface: {0}", sw.ElapsedMilliseconds); x = 3; sw = Stopwatch.StartNew(); for (int i = 0; i < Iterations; i++) { x = del(x); } sw.Stop(); Console.WriteLine("Delegate: {0}", sw.ElapsedMilliseconds); x = 3; sw = Stopwatch.StartNew(); for (int i = 0; i < Iterations; i++) { del = ifoo.Foo; x = del(x); } sw.Stop(); Console.WriteLine("Delegate with create of interface : {0}", sw.ElapsedMilliseconds); x = 3; sw = Stopwatch.StartNew(); for (int i = 0; i < Iterations; i++) { del = prog.Foo; x = del(x); } sw.Stop(); Console.WriteLine("Delegate with create : {0}", sw.ElapsedMilliseconds); x = 3; sw = Stopwatch.StartNew(); for (int i = 0; i < Iterations; i++) { x = heap_lambda.del(x); } sw.Stop(); Console.WriteLine("Heap Delegate lambda: {0}", sw.ElapsedMilliseconds); x = 3; sw = Stopwatch.StartNew(); for (int i = 0; i < Iterations; i++) { heap_lambda.del = y => y * 3; x = heap_lambda.del(x); } sw.Stop(); Console.WriteLine("Heap Delegate lambda with create : {0}", sw.ElapsedMilliseconds); Console.ReadLine(); } } } On Thu, Aug 29, 2013 at 12:36 PM, Bennie Kloosteman <[email protected]>wrote: > I call premature opt... espeically for a compiler.. :-) > > Just bench marked a delegate call vs an interface call (ms) > Interface: 28 > Delegate: 25 > Heap Delegate: 25 > Heap Delegate lambda: 31 > > Just in case it was doing something special with local declared delegate i > forced it to be in a heap option . > So stack delgate call was faster than interface and lambda not much slower > . DId not test on mono but its probably horrible, if anyone has it up i > would appreciate what bench mark you get .. > > However if you create a delegate for each case then its obviously much > slower. > > Anyway its pretty damn good and the difference is not worth altering a > design decision. > > Ben > > > using System; > using System.Collections.Generic; > using System.Diagnostics; > using System.Linq; > using System.Text; > using System.Threading.Tasks; > > namespace ConsoleApplication2 > { > > > public class A > { > public Func<int, int> del ; > } > > interface IFoo > { > int Foo(int x); > } > > class Program : IFoo > { > const int Iterations = 10000000; > > public int Foo(int x) > { > return x * 3; > } > > static void Main(string[] args) > { > var heap = new A(); > var heap_lambda = new A(); > int x = 3; > IFoo ifoo = new Program(); > Func<int, int> del = ifoo.Foo; > heap.del = ifoo.Foo; > heap_lambda .del = y => y * 3; > > // force compile > ifoo.Foo(3); > del(3); > heap.del(3); > heap_lambda.del(3); > > Stopwatch sw = Stopwatch.StartNew(); > for (int i = 0; i < Iterations; i++) > { > x = ifoo.Foo(x); > } > sw.Stop(); > Console.WriteLine("Interface: {0}", sw.ElapsedMilliseconds); > > x = 3; > sw = Stopwatch.StartNew(); > for (int i = 0; i < Iterations; i++) > { > x = del(x); > } > sw.Stop(); > Console.WriteLine("Delegate: {0}", sw.ElapsedMilliseconds); > > > > > x = 3; > sw = Stopwatch.StartNew(); > for (int i = 0; i < Iterations; i++) > { > x = heap.del(x); > } > sw.Stop(); > Console.WriteLine("Heap Delegate: {0}", sw.ElapsedMilliseconds); > > x = 3; > sw = Stopwatch.StartNew(); > for (int i = 0; i < Iterations; i++) > { > x = heap_lambda.del(x); > } > sw.Stop(); > Console.WriteLine("Heap Delegate lambda: {0}", > sw.ElapsedMilliseconds); > > Console.ReadLine(); > } > } > } > > > > > On Thu, Aug 29, 2013 at 12:36 AM, Jonathan S. Shapiro <[email protected]>wrote: > >> On Tuesday, August 27, 2013, David Jeske wrote: >> >>> On Tue, Aug 27, 2013 at 8:08 PM, Bennie Kloosteman >>> <[email protected]>wrote: >>> >>>> Hard to say without seeing more of the code , cant the unwind code be a >>>> method / Func delegate you pass in if its common code ? you can also use a >>>> helper something like >>>> >>> >>> I'm with Bennie here. Is there some reason this boilerplate is not >>> abstractable into a separate function? >>> >> >> Only the fact that delegate performance in CLR is horrible. >> >> _______________________________________________ >> bitc-dev mailing list >> [email protected] >> http://www.coyotos.org/mailman/listinfo/bitc-dev >> >> >
_______________________________________________ bitc-dev mailing list [email protected] http://www.coyotos.org/mailman/listinfo/bitc-dev
