using System; using System.Diagnostics; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using Xunit; namespace ReflectionPerformance { public class PerformanceRunner { public class Address { public String City { get; set; } } [Fact] public void RunAll() { // Remember to run it in RELEASE-mode (it makes a big difference) var address = new Address {City = "Trondheim"}; Run("Normal property access", () => { var city = address.City; }); var cityPropertyInfo = typeof (Address).GetProperty("City"); Run("With reflection", () => cityPropertyInfo.GetValue(address, new object[0])); Expression> expression = x => x.City; var func = expression.Compile(); Run("Invoke compiled expression", () => func.Invoke(address)); RunLong("Compile Expression and invoke", () => { var compiledFunction = expression.Compile(); compiledFunction.Invoke(address); }); var emitDelegate = GetEmitDelegate(); Run("Emit: run compiled statement", ()=>emitDelegate(address)); RunLong("Emit: Create statement, compile, run",()=>Emit(address)); } public void Emit(Address address) { var del = GetEmitDelegate(); del(address); } private Func GetEmitDelegate() { var dm = new DynamicMethod("TestMethod", typeof(String), new [] {typeof(Address) }, typeof(Address).Module); MethodInfo getCity = typeof(Address).GetProperty("City").GetGetMethod(); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.EmitCall(OpCodes.Call, getCity, null); il.Emit(OpCodes.Ret); return (Func)dm.CreateDelegate(typeof(Func)); } private const int timesToRun = 1000000; private void Run(String label, Action action) { var timer = new Stopwatch(); timer.Start(); for (int i = 0; i < timesToRun; i++) { action(); } timer.Stop(); Console.WriteLine(timer.ElapsedTicks.ToString().PadLeft(10) + " : " + label); } private void RunLong(String label, Action action) { var timer = new Stopwatch(); timer.Start(); for (int i = 0; i < timesToRun/100; i++) { action(); } timer.Stop(); Console.WriteLine((timer.ElapsedTicks * 100).ToString().PadLeft(10) + " : " + label); } } }