diff --git a/Benchmarks/Text/TextFormatter/StripCRLF.cs b/Benchmarks/Text/TextFormatter/StripCRLF.cs
new file mode 100644
index 000000000..069a23d92
--- /dev/null
+++ b/Benchmarks/Text/TextFormatter/StripCRLF.cs
@@ -0,0 +1,102 @@
+using System.Text;
+using BenchmarkDotNet.Attributes;
+using Tui = Terminal.Gui;
+
+namespace Terminal.Gui.Benchmarks.Text.TextFormatter;
+
+[MemoryDiagnoser]
+public class StripCRLF
+{
+ ///
+ /// Benchmark for previous implementation.
+ ///
+ ///
+ ///
+ ///
+ [Benchmark]
+ [ArgumentsSource (nameof (DataSource))]
+ public string Previous (string str, bool keepNewLine)
+ {
+ return RuneListToString (str, keepNewLine);
+ }
+
+ ///
+ /// Benchmark for current implementation with StringBuilder and char span index of search.
+ ///
+ [Benchmark (Baseline = true)]
+ [ArgumentsSource (nameof (DataSource))]
+ public string Current (string str, bool keepNewLine)
+ {
+ return Tui.TextFormatter.StripCRLF (str, keepNewLine);
+ }
+
+ ///
+ /// Previous implementation with intermediate list allocation.
+ ///
+ private static string RuneListToString (string str, bool keepNewLine = false)
+ {
+ List runes = str.ToRuneList ();
+
+ for (var i = 0; i < runes.Count; i++)
+ {
+ switch ((char)runes [i].Value)
+ {
+ case '\n':
+ if (!keepNewLine)
+ {
+ runes.RemoveAt (i);
+ }
+
+ break;
+
+ case '\r':
+ if (i + 1 < runes.Count && runes [i + 1].Value == '\n')
+ {
+ runes.RemoveAt (i);
+
+ if (!keepNewLine)
+ {
+ runes.RemoveAt (i);
+ }
+
+ i++;
+ }
+ else
+ {
+ if (!keepNewLine)
+ {
+ runes.RemoveAt (i);
+ }
+ }
+
+ break;
+ }
+ }
+
+ return StringExtensions.ToString (runes);
+ }
+
+ public IEnumerable