Performance of Value Tuples in C# - 1

C# 7 has introduced lots of new features. One of them is the new ValueTuples

Instead of discussing the compiler syntax and usage of value tuples, I suggest to search on the web, here is one great post C# 7 Series, Part 1: Value Tuples about it.

In this post I will do a small micro-benchmarking and also look at IL Code got generated for multiple return types.I will use an example where I have a possibility to return two values, but previously we have used one result parameter and out parameter: a TryParse method. It is made up sample code though, probably you would never have this business logic in a real application.

The Out parameter

[MethodImpl(MethodImplOptions.NoInlining)]
public static bool TryParse(out int value)
{
  value = 1;
  return true;
}

This method is being invoked 2000000000 times, in a for loop, and the result is added to a local variable. The average it takes to run this code takes 4122ms on a x64 machine. When I change the return value of this method to false, the tests takes an average of 4886ms, interestingly a little slower, however we do not add the value to the sum.

Averages are caluclated over 3 tests, disregarding the very first tests.

When we take a look at the IL generated, we see that our method is called, and based on the bool result, we branch and add/not add the parsed value to the sum.

tryparse-out

And the TryParse method itself:

tryparse-out1

Returning a ValueTuple

Let's re-write our TryParse method to return a ValueTuple with two parameters, the bool returning if the parse has succeeded and an integer, the parsed value.

[MethodImpl(MethodImplOptions.NoInlining)]
public static (bool, int) TryParse()
{
  return (true, 1);
}

and the invocation of this method:

(bool success, int parsed) = TryParse();
if(success)
{
  sum += parsed;
}

Running the same tests as for the previous TryParse (when true is being returned), we get an average execution time of 19027.3 ms. Changing to true return value to false the average is 18959 ms, which is about the same.

Now let's look at the IL Code generated at the invocation place:

value-out

We can see that a ValueTuple is being returned from our method, and it is being deconstructed into local that first needs to be stored and later loaded for the branch instructions.

The method itself also looks different, as we new up a ValueTuple value type:

value-out1