Style_Apply_Detach_Complex.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.CompilerServices;
  4. using Avalonia.Controls;
  5. using Avalonia.Styling;
  6. using Avalonia.UnitTests;
  7. using BenchmarkDotNet.Attributes;
  8. namespace Avalonia.Benchmarks.Styling
  9. {
  10. [MemoryDiagnoser]
  11. public class Style_Apply_Detach_Complex : IDisposable
  12. {
  13. private readonly IDisposable _app;
  14. private readonly TestRoot _root;
  15. private readonly TextBox _control;
  16. public Style_Apply_Detach_Complex()
  17. {
  18. _app = UnitTestApplication.Start(
  19. TestServices.StyledWindow.With(
  20. renderInterface: new NullRenderingPlatform(),
  21. threadingInterface: new NullThreadingPlatform()));
  22. // Simulate an application with a lot of styles by creating a tree of nested panels,
  23. // each with a bunch of styles applied.
  24. var (rootPanel, leafPanel) = CreateNestedPanels(10);
  25. // We're benchmarking how long it takes to apply styles to a TextBox in this situation.
  26. _control = new TextBox();
  27. leafPanel.Children.Add(_control);
  28. _root = new TestRoot(true, rootPanel)
  29. {
  30. Renderer = new NullRenderer(),
  31. };
  32. }
  33. [Benchmark]
  34. [MethodImpl(MethodImplOptions.NoInlining)]
  35. public void Apply_Detach_Styles()
  36. {
  37. // Styles will have already been attached when attached to the logical tree, so remove
  38. // the styles first.
  39. if ((string)_control.Tag != "TextBox")
  40. throw new Exception("Invalid benchmark state");
  41. ((IStyleable)_control).DetachStyles();
  42. if (_control.Tag is not null)
  43. throw new Exception("Invalid benchmark state");
  44. // Then re-apply the styles.
  45. _control.ApplyStyling();
  46. }
  47. public void Dispose()
  48. {
  49. _app.Dispose();
  50. }
  51. private static (Panel, Panel) CreateNestedPanels(int count)
  52. {
  53. var root = new Panel();
  54. var last = root;
  55. for (var i = 0; i < count; ++i)
  56. {
  57. var panel = new Panel();
  58. panel.Styles.AddRange(CreateStyles());
  59. last.Children.Add(panel);
  60. last = panel;
  61. }
  62. return (root, last);
  63. }
  64. private static IEnumerable<IStyle> CreateStyles()
  65. {
  66. var types = new[]
  67. {
  68. typeof(Border),
  69. typeof(Button),
  70. typeof(ButtonSpinner),
  71. typeof(Carousel),
  72. typeof(CheckBox),
  73. typeof(ComboBox),
  74. typeof(ContentControl),
  75. typeof(Expander),
  76. typeof(ItemsControl),
  77. typeof(Label),
  78. typeof(ListBox),
  79. typeof(ProgressBar),
  80. typeof(RadioButton),
  81. typeof(RepeatButton),
  82. typeof(ScrollViewer),
  83. typeof(Slider),
  84. typeof(Spinner),
  85. typeof(SplitView),
  86. typeof(TextBox),
  87. typeof(ToggleSwitch),
  88. typeof(TreeView),
  89. typeof(Viewbox),
  90. typeof(Window),
  91. };
  92. foreach (var type in types)
  93. {
  94. yield return new Style(x => x.OfType(type))
  95. {
  96. Setters = { new Setter(Control.TagProperty, type.Name) }
  97. };
  98. yield return new Style(x => x.OfType(type).Class("foo"))
  99. {
  100. Setters = { new Setter(Control.TagProperty, type.Name + " foo") }
  101. };
  102. yield return new Style(x => x.OfType(type).Class("bar"))
  103. {
  104. Setters = { new Setter(Control.TagProperty, type.Name + " bar") }
  105. };
  106. }
  107. }
  108. }
  109. }