diff options
Diffstat (limited to 'tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.cs')
-rw-r--r-- | tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.cs | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.cs b/tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.cs new file mode 100644 index 0000000000..660627cc72 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/Inlining/InlineGCStruct.cs @@ -0,0 +1,148 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// In CoreCLR String.Format(ref, ref) is small and readily inlined. +// The inline introduces a System.Parms GC struct local which is +// untracked and must be zero initialized in the prolog. When the +// inlined callsite is in a cold path, the inline hurts performance. +// +// There are two test methods below, one of which calls String.Format +// on a cold path and the other which has similar structure but +// does not call String.Format. Expectation is that they will have +// similar performance. +// +// See https://github.com/dotnet/coreclr/issues/7569 for context. + +using Microsoft.Xunit.Performance; +using System; +using System.Runtime.CompilerServices; +using Xunit; + +[assembly: OptimizeForBenchmarks] +[assembly: MeasureInstructionsRetired] + +namespace Inlining +{ +public class InlineGCStruct +{ +#if DEBUG + public const int Iterations = 1; +#else + public const int Iterations = 2500000; +#endif + + [MethodImpl(MethodImplOptions.NoInlining)] + public static int FastFunctionNotCallingStringFormat(int param) + { + if (param < 0) + { + throw new Exception(String.Format("We do not like the value {0:N0}.", param)); + } + + if (param == int.MaxValue) + { + throw new Exception(String.Format("{0:N0} is maxed out.", param)); + } + + if (param > int.MaxValue / 2) + { + throw new Exception(String.Format("We do not like the value {0:N0} either.", param)); + } + + return param * 2; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static int FastFunctionNotHavingStringFormat(int param) + { + if (param < 0) + { + throw new ArgumentOutOfRangeException("param", "We do not like this value."); + } + + if (param == int.MaxValue) + { + throw new ArgumentOutOfRangeException("param", "Maxed out."); + } + + if (param > int.MaxValue / 2) + { + throw new ArgumentOutOfRangeException("param", "We do not like this value either."); + } + + return param * 2; + } + + [Benchmark] + public static bool WithFormat() + { + int result = 0; + + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + for (int i = 0; i < Iterations; i++) + { + result |= FastFunctionNotCallingStringFormat(11); + } + } + } + + return (result == 22); + } + + [Benchmark] + public static bool WithoutFormat() + { + int result = 0; + + foreach (var iteration in Benchmark.Iterations) + { + using (iteration.StartMeasurement()) + { + for (int i = 0; i < Iterations; i++) + { + result |= FastFunctionNotHavingStringFormat(11); + } + } + } + + return (result == 22); + } + + public static bool WithoutFormatBase() + { + int result = 0; + + for (int i = 0; i < Iterations; i++) + { + result |= FastFunctionNotHavingStringFormat(11); + } + + return (result == 22); + } + + public static bool WithFormatBase() + { + int result = 0; + + for (int i = 0; i < Iterations; i++) + { + result |= FastFunctionNotCallingStringFormat(11); + } + + return (result == 22); + } + + public static int Main() + { + bool withFormat = WithFormatBase(); + bool withoutFormat = WithoutFormatBase(); + + return (withFormat && withoutFormat ? 100 : -1); + } +} +} + |