Advertisement
pipe012

LINQ Expressions benchmark

Aug 19th, 2019
228
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 2.75 KB | None | 0 0
  1. public class MyClass
  2. {
  3.     public string String { get; set; }
  4. }
  5.  
  6. class Program
  7. {
  8.     private const int Iterations = 10000;
  9.  
  10.     private static TimeSpan BaseLine;
  11.  
  12.     static void Main(string[] args)
  13.     {
  14.         var instance = new MyClass { String = "foo" };
  15.  
  16.         Benchmark(() => RawAccess(instance), true);
  17.         Benchmark(() => ReflectionNoCache(instance));
  18.         Benchmark(() => ReflectionWithCache(instance));
  19.         Benchmark(() => ExpressionNoCache(instance));
  20.         Benchmark(() => ExpressionWithCache(instance));
  21.  
  22.         Console.ReadKey(true);
  23.     }
  24.  
  25.     private static void RawAccess(MyClass obj)
  26.     {
  27.         _ = obj.String;
  28.     }
  29.  
  30.     private static void ReflectionNoCache(MyClass obj)
  31.     {
  32.         obj.GetType().GetProperty(nameof(MyClass.String)).GetValue(obj);
  33.     }
  34.  
  35.     private static PropertyInfo Prop;
  36.     private static void ReflectionWithCache(MyClass obj)
  37.     {
  38.         if (Prop == null)
  39.             Prop = obj.GetType().GetProperty(nameof(MyClass.String));
  40.  
  41.         Prop.GetValue(obj);
  42.     }
  43.  
  44.     private static void ExpressionNoCache(MyClass obj)
  45.     {
  46.         var expr = BuildExpression<MyClass, string>(nameof(MyClass.String));
  47.         var getter = expr.Compile();
  48.  
  49.         getter(obj);
  50.     }
  51.  
  52.     private static Func<MyClass, string> GetterFunc;
  53.     private static void ExpressionWithCache(MyClass obj)
  54.     {
  55.         if (GetterFunc == null)
  56.             GetterFunc = BuildExpression<MyClass, string>(nameof(MyClass.String)).Compile();
  57.  
  58.         GetterFunc(obj);
  59.     }
  60.  
  61.     private static Expression<Func<TClass, TProp>> BuildExpression<TClass, TProp>(string propName)
  62.     {
  63.         //You could also use an expression to get the property here like in the Benchmark method
  64.         var prop = typeof(TClass).GetProperty(propName);
  65.  
  66.         var instanceParam = Expression.Parameter(typeof(TClass), "instance");
  67.  
  68.         return Expression.Lambda<Func<TClass, TProp>>(Expression.Property(instanceParam, prop), instanceParam);
  69.     }
  70.  
  71.     public static TimeSpan Benchmark(Expression<Action> expr, bool isBaseline = false)
  72.     {
  73.         string name = ((MethodCallExpression)expr.Body).Method.Name; //Another use for expressions ;)
  74.         Console.Write($"{name,20}: ");
  75.  
  76.         var action = expr.Compile();
  77.         action(); //Run once first to build caches, otherwise the cached methods are at a big disadvantage
  78.  
  79.         var sw = Stopwatch.StartNew();
  80.  
  81.         for (int i = 0; i < Iterations; i++)
  82.         {
  83.             action();
  84.         }
  85.  
  86.         sw.Stop();
  87.  
  88.         if (isBaseline)
  89.             BaseLine = sw.Elapsed;
  90.  
  91.         Console.WriteLine($"{sw.Elapsed} b*{sw.Elapsed / BaseLine:0.0} ({sw.Elapsed.TotalMilliseconds / Iterations}ms per iteration)");
  92.  
  93.         return sw.Elapsed;
  94.     }
  95. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement