Performance of Value Tuples in C# - 2
06/16/2018
3 minutes
In the previous post I have shown how value tuples differ from having multiple out parameters. The IL code has been shown and some micro-benchmarking have been done.In this post I would like re-visit one very interesting question around the performance and the generated IL Code. When we know for sure, that one of the parameters of a method is not needed, we can use a (int success, _)
syntax to tell the C# compiler that we are only interested in the first parameter of the returned value tuple.
Here is the IL when we have both parameters used:
The previous post has shown that the average of deconstructing both parameters takes 18959 ms in that given test environment.
Test Method
So let's assume that we are only interested if the parse succeeds or not. Out test method is still the same,
[MethodImpl(MethodImplOptions.NoInlining)] public static (bool, int) TryParse() { return (false, 1); }
but we invoke it now differently:
(bool success, _) = TryParse(); if(success) { sum += 1; }
Running the tests again, we get an average of 20261,3 ms, which about the same as if we had not used the underscore for the parameter.
IL
Looking at the IL Code, we see can that the second parameter has not been stored and loaded on locals.
Conclusion
Though the IL code looks simpler, it is not gain much performance. Note, that the IL for the TryParse
method and the ValueTuple
being created and copied as a result has not changed, and it still needs to copy the same amount of bytes regardless of having underscore parameters.
Extra: Inlinening
Both examples in the previous and in this post uses NoInlinening attribute on the test methods.Changing this for AggressiveInlinening
suggests the compiler to inline the method and the place of invocation. This can improve the execution time, as we can save a whole method invocation.
Note, that the compiler itself looks out for methods to be inlined, and inlines them when possible. Also Note, that AggressiveInlinening does not mean that our method will be inlined. There are rules when a method can be inlined.
Repeating the previous tests with the out parameter results an average of 730.6 ms. The same for the ValueTuple is 17507 ms, which is only a slight improvement compared to the non-inlined version.