StringExtensions.ToString(IEnumerable<Rune>) use rented array as alternative buffer

This commit is contained in:
Tonttu
2025-03-16 07:31:33 +02:00
committed by Tig
parent 9b78961a03
commit cf2645fa04
2 changed files with 16 additions and 5 deletions

View File

@@ -22,7 +22,7 @@ public class ToStringEnumerable
}
/// <summary>
/// Benchmark for current implementation with stackalloc char buffer and
/// Benchmark for current implementation with char buffer and
/// fallback to rune chars appending to StringBuilder.
/// </summary>
/// <param name="runes"></param>

View File

@@ -127,7 +127,7 @@ public static class StringExtensions
const int maxCharsPerRune = 2;
const int maxStackallocTextBufferSize = 1048; // ~2 kB
// Use stackalloc buffer if rune count is easily available and the count is reasonable.
// If rune count is easily available use stackalloc buffer or alternatively rented array.
if (runes.TryGetNonEnumeratedCount (out int count))
{
if (count == 0)
@@ -135,10 +135,14 @@ public static class StringExtensions
return string.Empty;
}
int maxRequiredTextBufferSize = count * maxCharsPerRune;
if (maxRequiredTextBufferSize <= maxStackallocTextBufferSize)
char[]? rentedBufferArray = null;
try
{
Span<char> textBuffer = stackalloc char[maxRequiredTextBufferSize];
int maxRequiredTextBufferSize = count * maxCharsPerRune;
Span<char> textBuffer = maxRequiredTextBufferSize <= maxStackallocTextBufferSize
? stackalloc char[maxRequiredTextBufferSize]
: (rentedBufferArray = ArrayPool<char>.Shared.Rent(maxRequiredTextBufferSize));
Span<char> remainingBuffer = textBuffer;
foreach (Rune rune in runes)
{
@@ -149,6 +153,13 @@ public static class StringExtensions
ReadOnlySpan<char> text = textBuffer[..^remainingBuffer.Length];
return text.ToString ();
}
finally
{
if (rentedBufferArray != null)
{
ArrayPool<char>.Shared.Return (rentedBufferArray);
}
}
}
// Fallback to StringBuilder append.