Bepis
Bepis
CC#
Created by Bepis on 10/19/2024 in #help
Is there a faster way of splitting strings?
| Method | TestString | Mean | Error | StdDev |
|---------------------------- |----------- |----------:|----------:|---------:|
| BareImplementation | benchmarks | 25.90 ns | 4.169 ns | 2.481 ns |
| BareImplementationWithCheck | benchmarks | 16.13 ns | 2.335 ns | 1.389 ns |
| AsciiToLower | benchmarks | 40.56 ns | 1.616 ns | 0.845 ns |
| ToLowerInvariant | benchmarks | 47.25 ns | 0.531 ns | 0.278 ns |
| DeferredCreation | benchmarks | 136.06 ns | 9.650 ns | 5.743 ns |
| BareImplementation | BenchMarks | 21.46 ns | 1.496 ns | 0.890 ns |
| BareImplementationWithCheck | BenchMarks | 26.97 ns | 1.720 ns | 1.023 ns |
| AsciiToLower | BenchMarks | 40.60 ns | 1.062 ns | 0.555 ns |
| ToLowerInvariant | BenchMarks | 47.16 ns | 0.902 ns | 0.472 ns |
| DeferredCreation | BenchMarks | 147.46 ns | 10.854 ns | 5.677 ns |
| Method | TestString | Mean | Error | StdDev |
|---------------------------- |----------- |----------:|----------:|---------:|
| BareImplementation | benchmarks | 25.90 ns | 4.169 ns | 2.481 ns |
| BareImplementationWithCheck | benchmarks | 16.13 ns | 2.335 ns | 1.389 ns |
| AsciiToLower | benchmarks | 40.56 ns | 1.616 ns | 0.845 ns |
| ToLowerInvariant | benchmarks | 47.25 ns | 0.531 ns | 0.278 ns |
| DeferredCreation | benchmarks | 136.06 ns | 9.650 ns | 5.743 ns |
| BareImplementation | BenchMarks | 21.46 ns | 1.496 ns | 0.890 ns |
| BareImplementationWithCheck | BenchMarks | 26.97 ns | 1.720 ns | 1.023 ns |
| AsciiToLower | BenchMarks | 40.60 ns | 1.062 ns | 0.555 ns |
| ToLowerInvariant | BenchMarks | 47.16 ns | 0.902 ns | 0.472 ns |
| DeferredCreation | BenchMarks | 147.46 ns | 10.854 ns | 5.677 ns |
public class LowercaseBenchmark
{
[Params("benchmarks", "BenchMarks")]
public string TestString { get; set; }

[Benchmark]
public string BareImplementation()
{
ReadOnlySpan<char> span = TestString;
Span<char> chars = stackalloc char[span.Length];

for (int i = 0; i < span.Length; i++)
{
char c = span[i];
chars[i] = (c >= 'A' && c <= 'Z') ? (char)(c + 32) : c;
}

return new string(chars);
}

[Benchmark]
public string BareImplementationWithCheck()
{
ReadOnlySpan<char> span = TestString;

bool hasUppercase = false;
for (int i = 0; i < span.Length; i++)
{
char c = span[i];
if (c >= 'A' && c <= 'Z')
{
hasUppercase = true;
break;
}
}

if (!hasUppercase)
return new string(span);

Span<char> chars = stackalloc char[span.Length];

for (int i = 0; i < span.Length; i++)
{
char c = span[i];
chars[i] = (c >= 'A' && c <= 'Z') ? (char)(c + 32) : c;
}

return new string(chars);
}

[Benchmark]
public string AsciiToLower()
{
ReadOnlySpan<char> span = TestString;
Span<char> chars = stackalloc char[span.Length];

Ascii.ToLower(span, chars, out _);

return new string(chars);
}

[Benchmark]
public string ToLowerInvariant()
{
ReadOnlySpan<char> span = TestString;
Span<char> chars = stackalloc char[span.Length];

span.ToLowerInvariant(chars);

return new string(chars);
}

[Benchmark]
public string DeferredCreation()
{
ReadOnlySpan<char> span = TestString;

unsafe
{
var ptr = &span;
return String.Create(span.Length, (nint)ptr, static (buffer, ptr) =>
{
var span = *(ReadOnlySpan<char>*)ptr;
for (int i = 0; i < span.Length; i++)
{
char c = span[i];
buffer[i] = (c >= 'A' && c <= 'Z') ? (char)(c + 32) : c;
}
});
}
}
}
public class LowercaseBenchmark
{
[Params("benchmarks", "BenchMarks")]
public string TestString { get; set; }

[Benchmark]
public string BareImplementation()
{
ReadOnlySpan<char> span = TestString;
Span<char> chars = stackalloc char[span.Length];

for (int i = 0; i < span.Length; i++)
{
char c = span[i];
chars[i] = (c >= 'A' && c <= 'Z') ? (char)(c + 32) : c;
}

return new string(chars);
}

[Benchmark]
public string BareImplementationWithCheck()
{
ReadOnlySpan<char> span = TestString;

bool hasUppercase = false;
for (int i = 0; i < span.Length; i++)
{
char c = span[i];
if (c >= 'A' && c <= 'Z')
{
hasUppercase = true;
break;
}
}

if (!hasUppercase)
return new string(span);

Span<char> chars = stackalloc char[span.Length];

for (int i = 0; i < span.Length; i++)
{
char c = span[i];
chars[i] = (c >= 'A' && c <= 'Z') ? (char)(c + 32) : c;
}

return new string(chars);
}

[Benchmark]
public string AsciiToLower()
{
ReadOnlySpan<char> span = TestString;
Span<char> chars = stackalloc char[span.Length];

Ascii.ToLower(span, chars, out _);

return new string(chars);
}

[Benchmark]
public string ToLowerInvariant()
{
ReadOnlySpan<char> span = TestString;
Span<char> chars = stackalloc char[span.Length];

span.ToLowerInvariant(chars);

return new string(chars);
}

[Benchmark]
public string DeferredCreation()
{
ReadOnlySpan<char> span = TestString;

unsafe
{
var ptr = &span;
return String.Create(span.Length, (nint)ptr, static (buffer, ptr) =>
{
var span = *(ReadOnlySpan<char>*)ptr;
for (int i = 0; i < span.Length; i++)
{
char c = span[i];
buffer[i] = (c >= 'A' && c <= 'Z') ? (char)(c + 32) : c;
}
});
}
}
}
30 replies
CC#
Created by Bepis on 10/19/2024 in #help
Is there a faster way of splitting strings?
so it seems that ToLowerInvariant is faster in this context but not in the other
30 replies
CC#
Created by Bepis on 10/19/2024 in #help
Is there a faster way of splitting strings?
even more interestingly, it avgs at around 550ms
30 replies
CC#
Created by Bepis on 10/19/2024 in #help
Is there a faster way of splitting strings?
lets take a look
30 replies
CC#
Created by Bepis on 10/19/2024 in #help
Is there a faster way of splitting strings?
things that generally feel like they should perform better, don't
30 replies
CC#
Created by Bepis on 10/19/2024 in #help
Is there a faster way of splitting strings?
yes i think that sums up the last 4 or so hours i've been staring at this
30 replies
CC#
Created by Bepis on 10/19/2024 in #help
Is there a faster way of splitting strings?
this is actually slower as well somehow. for a 5MB batch of documents its avg is 500ms, the direct copy to stackalloc and checking each char avg is about 450ms
30 replies
CC#
Created by Bepis on 10/19/2024 in #help
Is there a faster way of splitting strings?
No description
30 replies