GetEncodingLength.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. using System.Text;
  2. using BenchmarkDotNet.Attributes;
  3. using Tui = Terminal.Gui;
  4. namespace Terminal.Gui.Benchmarks.Text.RuneExtensions;
  5. /// <summary>
  6. /// Benchmarks for <see cref="Tui.RuneExtensions.GetEncodingLength"/> performance fine-tuning.
  7. /// </summary>
  8. [MemoryDiagnoser]
  9. [BenchmarkCategory (nameof (Tui.RuneExtensions))]
  10. public class GetEncodingLength
  11. {
  12. /// <summary>
  13. /// Benchmark for previous implementation.
  14. /// </summary>
  15. [Benchmark]
  16. [ArgumentsSource (nameof (DataSource))]
  17. public int Previous (Rune rune, PrettyPrintedEncoding encoding)
  18. {
  19. return WithEncodingGetBytesArray (rune, encoding);
  20. }
  21. /// <summary>
  22. /// Benchmark for current implementation.
  23. /// </summary>
  24. [Benchmark (Baseline = true)]
  25. [ArgumentsSource (nameof (DataSource))]
  26. public int Current (Rune rune, PrettyPrintedEncoding encoding)
  27. {
  28. return Tui.RuneExtensions.GetEncodingLength (rune, encoding);
  29. }
  30. /// <summary>
  31. /// Previous implementation with intermediate byte array, string, and char array allocation.
  32. /// </summary>
  33. private static int WithEncodingGetBytesArray (Rune rune, Encoding? encoding = null)
  34. {
  35. encoding ??= Encoding.UTF8;
  36. byte [] bytes = encoding.GetBytes (rune.ToString ().ToCharArray ());
  37. var offset = 0;
  38. if (bytes [^1] == 0)
  39. {
  40. offset++;
  41. }
  42. return bytes.Length - offset;
  43. }
  44. public static IEnumerable<object []> DataSource ()
  45. {
  46. PrettyPrintedEncoding[] encodings = [ new(Encoding.UTF8), new(Encoding.Unicode), new(Encoding.UTF32) ];
  47. Rune[] runes = [ new Rune ('a'), "𝔹".EnumerateRunes ().Single () ];
  48. foreach (var encoding in encodings)
  49. {
  50. foreach (Rune rune in runes)
  51. {
  52. yield return [rune, encoding];
  53. }
  54. }
  55. }
  56. /// <summary>
  57. /// <see cref="System.Text.Encoding"/> wrapper to display proper encoding name in benchmark results.
  58. /// </summary>
  59. public record PrettyPrintedEncoding (Encoding Encoding)
  60. {
  61. public static implicit operator Encoding (PrettyPrintedEncoding ppe) => ppe.Encoding;
  62. public override string ToString () => Encoding.HeaderName;
  63. }
  64. }