Performance of Value Tuples in C# - 1
06/03/2018
3 minutes
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.
And the TryParse
method itself:
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:
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: