I just built a dynamic method - see below (thanks to other SO users). Func seems to have been created as a dynamic method with an injection of IL 2x slower than lambda.
Does anyone know why exactly?
(EDIT: It was released as an x64 version in VS2010. Run it from the console not from within Visual Studio F5.)
class Program { static void Main(string[] args) { var mul1 = IL_EmbedConst(5); var res = mul1(4); Console.WriteLine(res); var mul2 = EmbedConstFunc(5); res = mul2(4); Console.WriteLine(res); double d, acc = 0; Stopwatch sw = new Stopwatch(); for (int k = 0; k < 10; k++) { long time1; sw.Restart(); for (int i = 0; i < 10000000; i++) { d = mul2(i); acc += d; } sw.Stop(); time1 = sw.ElapsedMilliseconds; sw.Restart(); for (int i = 0; i < 10000000; i++) { d = mul1(i); acc += d; } sw.Stop(); Console.WriteLine("{0,6} {1,6}", time1, sw.ElapsedMilliseconds); } Console.WriteLine("\n{0}...\n", acc); Console.ReadLine(); } static Func<int, int> IL_EmbedConst(int b) { var method = new DynamicMethod("EmbedConst", typeof(int), new[] { typeof(int) } ); var il = method.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, b); il.Emit(OpCodes.Mul); il.Emit(OpCodes.Ret); return (Func<int, int>)method.CreateDelegate(typeof(Func<int, int>)); } static Func<int, int> EmbedConstFunc(int b) { return a => a * b; } }
Here is the conclusion (for i7 920)
20 20 25 51 25 51 24 51 24 51 24 51 25 51 25 51 25 51 24 51 24 51 4.9999995E+15...
==================================================== ============================
EDIT EDIT EDIT EDIT EDIT
Here's the proof that dhtorpe was right - a more complex lambda would lose its edge. Code for proof (this demonstrates that Lambda has exactly the same performance when injecting IL):
class Program { static void Main(string[] args) { var mul1 = IL_EmbedConst(5); double res = mul1(4,6); Console.WriteLine(res); var mul2 = EmbedConstFunc(5); res = mul2(4,6); Console.WriteLine(res); double d, acc = 0; Stopwatch sw = new Stopwatch(); for (int k = 0; k < 10; k++) { long time1; sw.Restart(); for (int i = 0; i < 10000000; i++) { d = mul2(i, i+1); acc += d; } sw.Stop(); time1 = sw.ElapsedMilliseconds; sw.Restart(); for (int i = 0; i < 10000000; i++) { d = mul1(i, i + 1); acc += d; } sw.Stop(); Console.WriteLine("{0,6} {1,6}", time1, sw.ElapsedMilliseconds); } Console.WriteLine("\n{0}...\n", acc); Console.ReadLine(); } static Func<int, int, double> IL_EmbedConst(int b) { var method = new DynamicMethod("EmbedConstIL", typeof(double), new[] { typeof(int), typeof(int) }); var log = typeof(Math).GetMethod("Log", new Type[] { typeof(double) }); var il = method.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, b); il.Emit(OpCodes.Mul); il.Emit(OpCodes.Conv_R8); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldc_I4, b); il.Emit(OpCodes.Mul); il.Emit(OpCodes.Conv_R8); il.Emit(OpCodes.Call, log); il.Emit(OpCodes.Sub); il.Emit(OpCodes.Ret); return (Func<int, int, double>)method.CreateDelegate(typeof(Func<int, int, double>)); } static Func<int, int, double> EmbedConstFunc(int b) { return (a, z) => a * b - Math.Log(z * b); } }