C# .NET Performance - Using Method Groups vs a Lambda with a Static method

When you use a Linq statement, the majority of the times you will pass it a lambda or a Method Group to process the logic within the Linq statement. This benchmark will test the performance of using a lambda and a method group.

Benchmarks and Results

public class MethodGroups
{
    private static readonly IEnumerable<int> ListOfInts = Enumerable.Range(1, 10_000).ToList();

    [Benchmark]
    // | Mean     |    Error |   StdDev | Allocated |
    // | 76.34 us | 0.257 us | 0.215 us |      40 B |
    public int Lambda_Static()
    {
        return ListOfInts.Count(x => ConditionStatic(x));
    }

    // | Mean     |    Error |   StdDev | Allocated |
    // | 82.73 us | 0.554 us | 0.491 us |      88 B |
    [Benchmark]
    public int MethodGroup_Static()
    {
        return ListOfInts.Count(ConditionStatic);
    }

    private static bool ConditionStatic(int value)
    {
        return value > 10;
    }

    // | Mean     |    Error |   StdDev | Allocated |
    // | 76.50 us | 0.486 us | 0.455 us |      88 B |
    [Benchmark]
    public int Lambda_Instance()
    {
        return ListOfInts.Count(x => ConditionInstance(x));
    }

    // | Mean     |    Error |   StdDev | Allocated |
    // | 76.41 us | 0.348 us | 0.309 us |      88 B |
    [Benchmark]
    public int MethodGroup_Instance()
    {
        return ListOfInts.Count(ConditionInstance);
    }

    private bool ConditionInstance(int value)
    {
        return value > 10;
    }
}

There are three noticeable differences:

  • Using an instance of the Condition method has the exact same behaviour across both the tests and the average time is somewhere around the same.
  • Using the Method Group approach with the static condition is slower than using the Lambda with the same method.
  • Method Group with the static condition approach allocates more than double the memory of the lambda with the same method. (This may be fixed in C# 11).

As there is more memory being allocated, the garbage collection will be triggered more often, which will cause a bigger impact on the performance of your application.

In C#10 and below, when using the lambda approach, it caches the reference to the static method and therefore any subsequent calls to the lambda uses the cached field. This does not happen with the Method Group approach.

If you want to see the lowered code and more details about this - there is a very interesting video by Nick Chapsas going through this exact scenario and the fix in C# 11 here. I definitely suggest you give it a watch!

Setup

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19044.1645 (21H2)
Intel Core i5-4460 CPU 3.20GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
.NET SDK=6.0.300-preview.22204.3
  [Host]     : .NET 5.0.15 (5.0.1522.11506), X64 RyuJIT
  CoreRT 6.0 : .NET 6.0.0-rc.1.21420.1, X64 AOT

Job=CoreRT 6.0  Runtime=CoreRT 6.0

Did you find this article valuable?

Support Mithilesh Zavar by becoming a sponsor. Any amount is appreciated!