Open2

C# Benchmark

rioilrioil
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;

namespace StringBenchmark
{
    internal class Program
    {
        static void Main(string[] args)
        {
            BenchmarkRunner.Run<StringStartsWithMeasurement>();
        }
    }

    [SimpleJob(RuntimeMoniker.Net472)]
    [SimpleJob(RuntimeMoniker.Net60)]
    public class StringStartsWithMeasurement
    {
        [Params("hoge")]
        public string Value = string.Empty;

        public string Start;

        [Params('a')]
        public char StartChar;

        [GlobalSetup]
        public void Setup()
        {
            Start = StartChar.ToString();
        }

        [Benchmark]
        public bool StartsWithString()
        {
            return Value.StartsWith(Start);
        }

        [Benchmark(Baseline = true)]
        public bool StartsWithChar()
        {
#if NETCOREAPP
            return Value.StartsWith(StartChar);
#else
            return Value.Length != 0 && Value[0] == StartChar;
#endif
        }
    }
}
// * Summary *

BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19045.2965/22H2/2022Update)
11th Gen Intel Core i7-11700K 3.60GHz, 1 CPU, 16 logical and 8 physical cores
  [Host]               : .NET Framework 4.8 (4.8.4614.0), X64 RyuJIT VectorSize=256
  .NET 6.0             : .NET 6.0.16 (6.0.1623.17311), X64 RyuJIT AVX2
  .NET Framework 4.7.2 : .NET Framework 4.8 (4.8.4614.0), X64 RyuJIT VectorSize=256


|           Method |                  Job |              Runtime | Value | StartChar |        Mean |     Error |    StdDev |    Ratio |  RatioSD |
|----------------- |--------------------- |--------------------- |------ |---------- |------------:|----------:|----------:|---------:|---------:|
| StartsWithString |             .NET 6.0 |             .NET 6.0 |  hoge |         a | 411.7495 ns | 4.9672 ns | 4.4033 ns | 8,972.02 | 4,838.40 |
|   StartsWithChar |             .NET 6.0 |             .NET 6.0 |  hoge |         a |   0.0542 ns | 0.0226 ns | 0.0211 ns |     1.00 |     0.00 |
|                  |                      |                      |       |           |             |           |           |          |          |
| StartsWithString | .NET Framework 4.7.2 | .NET Framework 4.7.2 |  hoge |         a |  75.1370 ns | 1.0416 ns | 0.8698 ns |   321.76 |    28.45 |
|   StartsWithChar | .NET Framework 4.7.2 | .NET Framework 4.7.2 |  hoge |         a |   0.2369 ns | 0.0205 ns | 0.0192 ns |     1.00 |     0.00 |

// * Hints *
Outliers
  StringStartsWithMeasurement.StartsWithString: .NET 6.0             -> 1 outlier  was  removed (433.87 ns)
  StringStartsWithMeasurement.StartsWithChar: .NET 6.0               -> 2 outliers were removed (1.22 ns, 1.26 ns)
  StringStartsWithMeasurement.StartsWithString: .NET Framework 4.7.2 -> 4 outliers were removed (81.08 ns..113.23 ns)

// * Legends *
  Value     : Value of the 'Value' parameter
  StartChar : Value of the 'StartChar' parameter
  Mean      : Arithmetic mean of all measurements
  Error     : Half of 99.9% confidence interval
  StdDev    : Standard deviation of all measurements
  Ratio     : Mean of the ratio distribution ([Current]/[Baseline])
  RatioSD   : Standard deviation of the ratio distribution ([Current]/[Baseline])
  1 ns      : 1 Nanosecond (0.000000001 sec)

// ***** BenchmarkRunner: End *****
Run time: 00:01:39 (99.48 sec), executed benchmarks: 4

Global total time: 00:01:45 (105.41 sec), executed benchmarks: 4
// * Artifacts cleanup *
rioilrioil
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;

namespace StringBenchmark
{
    internal class Program
    {
        static void Main(string[] args)
        {
            BenchmarkRunner.Run<StringStartsWithMeasurement>();
        }
    }

    [SimpleJob(RuntimeMoniker.Net472)]
    [SimpleJob(RuntimeMoniker.Net60)]
    [SimpleJob(RuntimeMoniker.Net80)]
    public class StringStartsWithMeasurement
    {
        [Params("hoge")]
        public string Value = string.Empty;
        public char ValueFirstChar;

        public string Start;

        [Params('a')]
        public char StartChar;

        [GlobalSetup]
        public void Setup()
        {
            Start = StartChar.ToString();
            ValueFirstChar = Value[0];
        }

        [Benchmark]
        public bool StartsWithString()
        {
            return Value.StartsWith(Start);
        }

        [Benchmark]
        public bool StartsWithChar()
        {
            return Value.StartsWith(StartChar);
        }

        [Benchmark(Baseline = true)]
        public bool StartsWithCharInline()
        {
            return Value.Length != 0 && ValueFirstChar == StartChar;
        }
    }

#if !NETCOREAPP
    public static class StringExtensions
    {
        public static bool StartsWith(this string value, char c)
        {
            return value.Length != 0 && value[0] == c;
        }
    }
#endif
}
// * Summary *

BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19045.3930/22H2/2022Update)
11th Gen Intel Core i7-11700K 3.60GHz, 1 CPU, 16 logical and 8 physical cores
  [Host]               : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT VectorSize=256
  .NET 6.0             : .NET 6.0.26 (6.0.2623.60508), X64 RyuJIT AVX2
  .NET 8.0             : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
  .NET Framework 4.7.2 : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT VectorSize=256


|               Method |                  Job |              Runtime | Value | StartChar |        Mean |     Error |    StdDev |      Median |     Ratio |   RatioSD |
|--------------------- |--------------------- |--------------------- |------ |---------- |------------:|----------:|----------:|------------:|----------:|----------:|
|     StartsWithString |             .NET 6.0 |             .NET 6.0 |  hoge |         a | 431.5507 ns | 5.3370 ns | 4.9922 ns | 432.4835 ns |         ? |         ? |
|       StartsWithChar |             .NET 6.0 |             .NET 6.0 |  hoge |         a |   0.0002 ns | 0.0009 ns | 0.0008 ns |   0.0000 ns |         ? |         ? |
| StartsWithCharInline |             .NET 6.0 |             .NET 6.0 |  hoge |         a |   0.0023 ns | 0.0061 ns | 0.0054 ns |   0.0000 ns |         ? |         ? |
|                      |                      |                      |       |           |             |           |           |             |           |           |
|     StartsWithString |             .NET 8.0 |             .NET 8.0 |  hoge |         a | 391.5178 ns | 5.3790 ns | 5.0316 ns | 391.5569 ns | 12,366.17 | 12,603.52 |
|       StartsWithChar |             .NET 8.0 |             .NET 8.0 |  hoge |         a |   0.5557 ns | 0.0168 ns | 0.0158 ns |   0.5571 ns |     17.59 |     17.83 |
| StartsWithCharInline |             .NET 8.0 |             .NET 8.0 |  hoge |         a |   0.0501 ns | 0.0238 ns | 0.0293 ns |   0.0476 ns |      1.00 |      0.00 |
|                      |                      |                      |       |           |             |           |           |             |           |           |
|     StartsWithString | .NET Framework 4.7.2 | .NET Framework 4.7.2 |  hoge |         a |  71.8030 ns | 1.4381 ns | 1.4768 ns |  71.7366 ns |         ? |         ? |
|       StartsWithChar | .NET Framework 4.7.2 | .NET Framework 4.7.2 |  hoge |         a |   0.6707 ns | 0.0290 ns | 0.0271 ns |   0.6792 ns |         ? |         ? |
| StartsWithCharInline | .NET Framework 4.7.2 | .NET Framework 4.7.2 |  hoge |         a |   0.0000 ns | 0.0000 ns | 0.0000 ns |   0.0000 ns |         ? |         ? |

// * Warnings *
ZeroMeasurement
  StringStartsWithMeasurement.StartsWithChar: .NET 6.0                   -> The method duration is indistinguishable from the empty method duration
  StringStartsWithMeasurement.StartsWithCharInline: .NET 6.0             -> The method duration is indistinguishable from the empty method duration
  StringStartsWithMeasurement.StartsWithCharInline: .NET Framework 4.7.2 -> The method duration is indistinguishable from the empty method duration
BaselineCustomAnalyzer
  Summary -> A question mark '?' symbol indicates that it was not possible to compute the (Ratio, RatioSD) column(s) because the baseline value is too close to zero.

// * Hints *
Outliers
  StringStartsWithMeasurement.StartsWithString: .NET 6.0           -> 1 outlier  was  detected (420.34 ns)
  StringStartsWithMeasurement.StartsWithChar: .NET 6.0             -> 1 outlier  was  removed (1.12 ns)
  StringStartsWithMeasurement.StartsWithCharInline: .NET 6.0       -> 1 outlier  was  removed (1.13 ns)
  StringStartsWithMeasurement.StartsWithCharInline: .NET 8.0       -> 1 outlier  was  removed (1.33 ns)
  StringStartsWithMeasurement.StartsWithChar: .NET Framework 4.7.2 -> 2 outliers were removed (1.83 ns, 1.84 ns)

// * Legends *
  Value     : Value of the 'Value' parameter
  StartChar : Value of the 'StartChar' parameter
  Mean      : Arithmetic mean of all measurements
  Error     : Half of 99.9% confidence interval
  StdDev    : Standard deviation of all measurements
  Median    : Value separating the higher half of all measurements (50th percentile)
  Ratio     : Mean of the ratio distribution ([Current]/[Baseline])
  RatioSD   : Standard deviation of the ratio distribution ([Current]/[Baseline])
  1 ns      : 1 Nanosecond (0.000000001 sec)

// ***** BenchmarkRunner: End *****
Run time: 00:04:29 (269 sec), executed benchmarks: 9

Global total time: 00:04:36 (276.11 sec), executed benchmarks: 9
// * Artifacts cleanup *