1
0

Style_Apply_Detach_Complex.cs 3.7 KB

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