瀏覽代碼

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

Tonttu 4 月之前
父節點
當前提交
cf2645fa04
共有 2 個文件被更改,包括 16 次插入5 次删除
  1. 1 1
      Benchmarks/Text/StringExtensions/ToStringEnumerable.cs
  2. 15 4
      Terminal.Gui/Text/StringExtensions.cs

+ 1 - 1
Benchmarks/Text/StringExtensions/ToStringEnumerable.cs

@@ -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>

+ 15 - 4
Terminal.Gui/Text/StringExtensions.cs

@@ -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.