Skip to content

Instantly share code, notes, and snippets.

@michal-ciechan
Created December 6, 2022 07:48
Show Gist options
  • Save michal-ciechan/0a53518076bff6253395d6456dc9f11f to your computer and use it in GitHub Desktop.
Save michal-ciechan/0a53518076bff6253395d6456dc9f11f to your computer and use it in GitHub Desktop.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
namespace MikeysBenchmarks;
[SimpleJob(RuntimeMoniker.Net70)]
[MemoryDiagnoser()]
[MarkdownExporter]
public class SpanTrimZ
{
private const string _withUtc = "2022-12-05T11:11:23Z";
private const string _withoutUtc = "2022-12-05T11:11:23";
private static readonly char[] _z = new char[1]
{
'Z'
};
[GlobalSetup]
public void GlobalSetup()
{
}
[ParamsAllValues]
public bool WithUtc { get; set; }
public string String => WithUtc ? _withUtc : _withoutUtc;
[Benchmark]
public int StringTrimEnd()
{
var str = String.TrimEnd('Z').TrimEnd('z');
var isUtc = str.Length < String.Length;
var utcOffset = isUtc ? 1 : 0;
return str.Length + utcOffset;
}
[Benchmark]
public int CompareStackalloc_TrimEnd()
{
var span = String.AsSpan();
var utcOffset = 0;
Span<char> s = stackalloc char[1]
{
'Z'
};
if (span.EndsWith(s, StringComparison.OrdinalIgnoreCase))
{
span = span.TrimEnd('Z').TrimEnd('z');
utcOffset = 1;
}
return span.Length + utcOffset;
}
[Benchmark]
public int CompareStackalloc_Range()
{
var span = String.AsSpan();
var utcOffset = 0;
Span<char> s = stackalloc char[1]
{
'Z'
};
if (span.EndsWith(s, StringComparison.OrdinalIgnoreCase))
{
span = span[..^1];
utcOffset = 1;
}
return span.Length + utcOffset;
}
[Benchmark]
public int CompareStackalloc_Length()
{
var span = String.AsSpan();
var utcOffset = 0;
Span<char> s = stackalloc char[1]
{
'Z'
};
if (span.EndsWith(s, StringComparison.OrdinalIgnoreCase))
{
span = span.Slice(0, span.Length - 1);
utcOffset = 1;
}
return span.Length + utcOffset;
}
[Benchmark]
public int CompareArray_Length()
{
var span = String.AsSpan();
var utcOffset = 0;
var c = _z.AsSpan();
if (span.EndsWith(c, StringComparison.OrdinalIgnoreCase))
{
span = span.Slice(0, span.Length - 1);
utcOffset = 1;
}
return span.Length + utcOffset;
}
[Benchmark]
public int CompareArray_Range()
{
var span = String.AsSpan();
var utcOffset = 0;
var c = _z.AsSpan();
if (span.EndsWith(c, StringComparison.OrdinalIgnoreCase))
{
span = span[..^1];
utcOffset = 1;
}
return span.Length + utcOffset;
}
[Benchmark]
public int CompareArray_TrimEnd()
{
var span = String.AsSpan();
var utcOffset = 0;
var c = _z.AsSpan();
if (span.EndsWith(c, StringComparison.OrdinalIgnoreCase))
{
span = span.TrimEnd('Z').TrimEnd('z');
utcOffset = 1;
}
return span.Length + utcOffset;
}
[Benchmark]
public int StringEndsWith_Range()
{
var span = String.AsSpan();
var utcOffset = 0;
if (String.EndsWith("Z", StringComparison.OrdinalIgnoreCase))
{
span = span[..^1];
utcOffset = 1;
}
return span.Length + utcOffset;
}
[Benchmark]
public int SpanTrimEndWithCheck()
{
var span = String.AsSpan();
var span2 = span.TrimEnd('Z').TrimEnd('z');
var isUtc = span2.Length < span.Length;
var utcOffset = isUtc ? 1 : 0;
return span.Length + utcOffset;
}
}
/*
// * Summary *
BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19043.1348/21H1/May2021Update), VM=VMware
AMD EPYC 7713P, 1 CPU, 12 logical and 12 physical cores
.NET SDK=7.0.100-rc.2.22477.23
[Host] : .NET 6.0.10 (6.0.1022.47605), X64 RyuJIT AVX2
.NET 7.0 : .NET 7.0.0 (7.0.22.47203), X64 RyuJIT AVX2
Job=.NET 7.0 Runtime=.NET 7.0
| Method | WithUtc | Mean | Error | StdDev | Gen0 | Allocated |
|-------------------------- |-------- |----------:|----------:|----------:|-------:|----------:|
| StringTrimEnd | False | 10.510 ns | 0.2319 ns | 0.1936 ns | - | - |
| CompareStackalloc_TrimEnd | False | 5.326 ns | 0.0705 ns | 0.0589 ns | - | - |
| CompareStackalloc_Range | False | 5.812 ns | 0.1114 ns | 0.0987 ns | - | - |
| CompareStackalloc_Length | False | 5.555 ns | 0.1105 ns | 0.1033 ns | - | - |
| CompareArray_Length | False | 5.026 ns | 0.0475 ns | 0.0371 ns | - | - |
| CompareArray_Range | False | 5.013 ns | 0.0982 ns | 0.0918 ns | - | - |
| CompareArray_TrimEnd | False | 5.426 ns | 0.1222 ns | 0.1143 ns | - | - |
| StringEndsWith_Range | False | 9.735 ns | 0.1929 ns | 0.1804 ns | - | - |
| SpanTrimEndWithCheck | False | 2.866 ns | 0.0879 ns | 0.0822 ns | - | - |
| StringTrimEnd | True | 22.666 ns | 0.3861 ns | 0.3423 ns | 0.0007 | 64 B |
| CompareStackalloc_TrimEnd | True | 6.663 ns | 0.0746 ns | 0.0582 ns | - | - |
| CompareStackalloc_Range | True | 5.308 ns | 0.0518 ns | 0.0405 ns | - | - |
| CompareStackalloc_Length | True | 5.114 ns | 0.1376 ns | 0.1287 ns | - | - |
| CompareArray_Length | True | 4.364 ns | 0.0474 ns | 0.0420 ns | - | - |
| CompareArray_Range | True | 4.387 ns | 0.0618 ns | 0.0548 ns | - | - |
| CompareArray_TrimEnd | True | 6.434 ns | 0.1147 ns | 0.1178 ns | - | - |
| StringEndsWith_Range | True | 10.174 ns | 0.2208 ns | 0.2168 ns | - | - |
| SpanTrimEndWithCheck | True | 4.105 ns | 0.0843 ns | 0.0788 ns | - | - |
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment