using System.Text; using BenchmarkDotNet.Attributes; using Tui = Terminal.Gui; namespace Terminal.Gui.Benchmarks.Text.RuneExtensions; /// /// Benchmarks for performance fine-tuning. /// [MemoryDiagnoser] [BenchmarkCategory (nameof (Tui.RuneExtensions))] public class GetEncodingLength { /// /// Benchmark for previous implementation. /// [Benchmark] [ArgumentsSource (nameof (DataSource))] public int Previous (Rune rune, PrettyPrintedEncoding encoding) { return WithEncodingGetBytesArray (rune, encoding); } /// /// Benchmark for current implementation. /// [Benchmark (Baseline = true)] [ArgumentsSource (nameof (DataSource))] public int Current (Rune rune, PrettyPrintedEncoding encoding) { return Tui.RuneExtensions.GetEncodingLength (rune, encoding); } /// /// Previous implementation with intermediate byte array, string, and char array allocation. /// private static int WithEncodingGetBytesArray (Rune rune, Encoding? encoding = null) { encoding ??= Encoding.UTF8; byte [] bytes = encoding.GetBytes (rune.ToString ().ToCharArray ()); var offset = 0; if (bytes [^1] == 0) { offset++; } return bytes.Length - offset; } public static IEnumerable DataSource () { PrettyPrintedEncoding[] encodings = [ new(Encoding.UTF8), new(Encoding.Unicode), new(Encoding.UTF32) ]; Rune[] runes = [ new Rune ('a'), "𝔹".EnumerateRunes ().Single () ]; foreach (var encoding in encodings) { foreach (Rune rune in runes) { yield return [rune, encoding]; } } } /// /// wrapper to display proper encoding name in benchmark results. /// public record PrettyPrintedEncoding (Encoding Encoding) { public static implicit operator Encoding (PrettyPrintedEncoding ppe) => ppe.Encoding; public override string ToString () => Encoding.HeaderName; } }