Building Functions vs. Building Expressions: Performance Comparison

Yesterday I posted an entry describing a method for building functions as opposed to building expressions to get a more succinct syntax, and in general a more functional approach. There was a touch of reflection in there though, so I wasn’t too sure what the performance would be like.

Even though the post was specifically about an alternative to building expressions, the commenter suggested that it was more efficient, based on his own benchmarks. I was shocked.

Not being the type to believe something without seeing it, I found myself compelled to write my own simple benchmark and the results were shocking.

Building functions is FASTER than building expressions. WAY faster. Let’s take a look:

The Code:

The function building method I created was this (again sorry for the formatting – I’m trying to make it fit):

   1:  public static Func<T, bool> BuildEqFuncFor<T>
   2:      (string prop, object val)
   3:  {
   4:      return t => t.GetType()
   5:          .InvokeMember(prop, 
   6:              BindingFlags.GetProperty, 
   7:              null, 
   8:              t, 
   9:              null) == val;
  10:  }

And the commenter suggested I use the approach where you build up an expression, and then compile it:

   1:  public static Func<T, bool> ExBuildEqFuncFor<T>
   2:      (string prop, object val)
   3:  {
   4:      var o = Expression.Parameter(typeof(T), "t");
   5:   
   6:      Expression<Func<T, bool>> expression = 
   7:          Expression.Lambda<Func<T, bool>>(
   8:              Expression.Equal(
   9:                  Expression.PropertyOrField(o, prop), 
  10:                  Expression.Constant(val)), o);
  11:   
  12:      return expression.Compile();
  13:  }

The Results:

I ran each method 1, 100, and 10,000 times and here were the results (in seconds):

buildfuncVSbuildexpBenchmarks

It’s unbelievable how much faster the function building method ran, compared to creating an expression tree and compiling it. In fact, within 100 runs there was almost no change at all!

I looked into what was making the expression building function so long to create, and as I suspected it was the “Compile” method call that is used to turn the whole tree into a function. I changed the method to just return the expression and not compile it and re-ran the tests. It still took twice as long just to build the expression as it did to build an actual function.

If you think about it though, it makes sense. Compiling on the fly was never supposed to be considered a performant (yes I said “performant”) method of metaprogramming in C# and if you are going to use it, it would be wise to implement some caching to prevent the need to constantly build the same functions again and again.

Or, you can just build the functions directly.

2 Comments

  • If you're only planning to use each function once then you are correct. Building functions your way is faster than building the expressions. In fact, you're not really even "building" the functions at run time; they are built at compile time, and then use reflection to "run" the functions.

    However, if you're planning to use each expression 100 times, the tables turn. Your function, although quick to "build," is far slower to run because it relies on reflection.

  • Has anyone benchmarked the performance of the actual generated function (ie. one built with Func vs. expression trees). Is it worth the extra overhead of compiling the expression tree if the function will be used in a heavily threaded application many times?

Comments have been disabled for this content.