// File RTCG4.cs --- the power example // sestoft@itu.dk * 2002 // A reflective call to specialized: 25.0 sec // A delegate call to specialized: 0.671 // Static call to general compiled: 0.751 // Delegate call to general compiled: 1.06 using System; using System.Reflection; using System.Reflection.Emit; class RTCG4 { public static void Main(String [] args) { int count = int.Parse(args[0]); int n = 16; AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = "myassembly"; // Build: run-only assembly AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); // Build: module mymodule ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("mymodule"); // Build: public class MyClass { ... } TypeBuilder typeBuilder = moduleBuilder.DefineType("MyClass", TypeAttributes.Class | TypeAttributes.Public, typeof(Object)); { // Build: public static int MyPower(int x) { ... } MethodBuilder methodBuilder = typeBuilder.DefineMethod("MyPower", MethodAttributes.Static | MethodAttributes.Public, typeof(int), new Type[] { typeof(int) }); // Obtain an IL generator to build the method body ILGenerator ilg = methodBuilder.GetILGenerator(); PowerGen(ilg, n); } Type ty = typeBuilder.CreateType(); int res = 0; Timer t1 = new Timer(); object[] arglist = new object[] { 3 }; MethodInfo mypowerMethod = ty.GetMethod("MyPower"); for (int i=count; i>0; i--) res = (int)mypowerMethod.Invoke(null, arglist); Console.WriteLine("Reflective call to specialized generated method: " + t1.Check() + " sec"); Console.WriteLine(res); Timer t2 = new Timer(); Int2Int power_n = (Int2Int)Delegate.CreateDelegate(typeof(Int2Int), mypowerMethod); for (int i=count; i>0; i--) res = power_n(3); Console.WriteLine("Delegate call to specialized generated method: " + t2.Check() + " sec"); Console.WriteLine(res); Timer t3 = new Timer(); for (int i=count; i>0; i--) res = Power(n, 3); Console.WriteLine("Static call to general compiled method: " + t3.Check() + " sec"); Console.WriteLine(res); Timer t4 = new Timer(); IntInt2Int power = new IntInt2Int(Power); for (int i=count; i>0; i--) res = power(n, 3); Console.WriteLine("Delegate call to general compiled method: " + t4.Check() + " sec"); Console.WriteLine(res); } public static int Power(int n, int x) { int p; p = 1; while (n > 0) { if (n % 2 == 0) { x = x * x; n = n / 2; } else { p = p * x; n = n - 1; } } return p; } public static void PowerGen(ILGenerator ilg, int n) { ilg.DeclareLocal(typeof(int)); // p is local_0, x is arg_0 ilg.Emit(OpCodes.Ldc_I4_1); ilg.Emit(OpCodes.Stloc_0); // p = 1; while (n > 0) { if (n % 2 == 0) { ilg.Emit(OpCodes.Ldarg_0); // x is arg_0 ilg.Emit(OpCodes.Ldarg_0); ilg.Emit(OpCodes.Mul); ilg.Emit(OpCodes.Starg_S, 0); // x = x * x n = n / 2; } else { ilg.Emit(OpCodes.Ldloc_0); ilg.Emit(OpCodes.Ldarg_0); ilg.Emit(OpCodes.Mul); ilg.Emit(OpCodes.Stloc_0); // p = p * x; n = n - 1; } } ilg.Emit(OpCodes.Ldloc_0); ilg.Emit(OpCodes.Ret); // return p; } public delegate int Int2Int(int x); public delegate int IntInt2Int(int x, int y); } // Crude timing utility ---------------------------------------- public class Timer { private DateTime start; public Timer() { start = DateTime.Now; } public double Check() { TimeSpan dur = DateTime.Now - start; return dur.TotalSeconds; } }