Browse Source
Now tries to simulate an application with a lot of styles applied at different points in the logical tree. Make `StyledElement.ApplyStyling` a public API in order to do this.pull/9411/head
3 changed files with 131 additions and 48 deletions
@ -1,47 +0,0 @@ |
|||
using System; |
|||
using System.Runtime.CompilerServices; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Styling; |
|||
using Avalonia.UnitTests; |
|||
using BenchmarkDotNet.Attributes; |
|||
|
|||
namespace Avalonia.Benchmarks.Styling |
|||
{ |
|||
[MemoryDiagnoser] |
|||
public class StyleAttachBenchmark : IDisposable |
|||
{ |
|||
private readonly IDisposable _app; |
|||
private readonly TestRoot _root; |
|||
private readonly TextBox _control; |
|||
|
|||
public StyleAttachBenchmark() |
|||
{ |
|||
_app = UnitTestApplication.Start( |
|||
TestServices.StyledWindow.With( |
|||
renderInterface: new NullRenderingPlatform(), |
|||
threadingInterface: new NullThreadingPlatform())); |
|||
|
|||
_root = new TestRoot(true, null) |
|||
{ |
|||
Renderer = new NullRenderer(), |
|||
}; |
|||
|
|||
_control = new TextBox(); |
|||
} |
|||
|
|||
[Benchmark] |
|||
[MethodImpl(MethodImplOptions.NoInlining)] |
|||
public void AttachTextBoxStyles() |
|||
{ |
|||
var styles = UnitTestApplication.Current.Styles; |
|||
|
|||
styles.TryAttach(_control, UnitTestApplication.Current); |
|||
((IStyleable)_control).DetachStyles(); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
_app.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,126 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Runtime.CompilerServices; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Styling; |
|||
using Avalonia.UnitTests; |
|||
using BenchmarkDotNet.Attributes; |
|||
|
|||
namespace Avalonia.Benchmarks.Styling |
|||
{ |
|||
[MemoryDiagnoser] |
|||
public class Style_Apply_Detach_Complex : IDisposable |
|||
{ |
|||
private readonly IDisposable _app; |
|||
private readonly TestRoot _root; |
|||
private readonly TextBox _control; |
|||
|
|||
public Style_Apply_Detach_Complex() |
|||
{ |
|||
_app = UnitTestApplication.Start( |
|||
TestServices.StyledWindow.With( |
|||
renderInterface: new NullRenderingPlatform(), |
|||
threadingInterface: new NullThreadingPlatform())); |
|||
|
|||
// Simulate an application with a lot of styles by creating a tree of nested panels,
|
|||
// each with a bunch of styles applied.
|
|||
var (rootPanel, leafPanel) = CreateNestedPanels(10); |
|||
|
|||
// We're benchmarking how long it takes to apply styles to a TextBox in this situation.
|
|||
_control = new TextBox(); |
|||
leafPanel.Children.Add(_control); |
|||
|
|||
_root = new TestRoot(true, rootPanel) |
|||
{ |
|||
Renderer = new NullRenderer(), |
|||
}; |
|||
} |
|||
|
|||
[Benchmark] |
|||
[MethodImpl(MethodImplOptions.NoInlining)] |
|||
public void Apply_Detach_Styles() |
|||
{ |
|||
// Styles will have already been attached when attached to the logical tree, so remove
|
|||
// the styles first.
|
|||
if ((string)_control.Tag != "TextBox") |
|||
throw new Exception("Invalid benchmark state"); |
|||
|
|||
((IStyleable)_control).DetachStyles(); |
|||
|
|||
if (_control.Tag is not null) |
|||
throw new Exception("Invalid benchmark state"); |
|||
|
|||
// Then re-apply the styles.
|
|||
_control.ApplyStyling(); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
_app.Dispose(); |
|||
} |
|||
|
|||
private static (Panel, Panel) CreateNestedPanels(int count) |
|||
{ |
|||
var root = new Panel(); |
|||
var last = root; |
|||
|
|||
for (var i = 0; i < count; ++i) |
|||
{ |
|||
var panel = new Panel(); |
|||
panel.Styles.AddRange(CreateStyles()); |
|||
last.Children.Add(panel); |
|||
last = panel; |
|||
} |
|||
|
|||
return (root, last); |
|||
} |
|||
|
|||
private static IEnumerable<IStyle> CreateStyles() |
|||
{ |
|||
var types = new[] |
|||
{ |
|||
typeof(Border), |
|||
typeof(Button), |
|||
typeof(ButtonSpinner), |
|||
typeof(Carousel), |
|||
typeof(CheckBox), |
|||
typeof(ComboBox), |
|||
typeof(ContentControl), |
|||
typeof(Expander), |
|||
typeof(ItemsControl), |
|||
typeof(Label), |
|||
typeof(ListBox), |
|||
typeof(ProgressBar), |
|||
typeof(RadioButton), |
|||
typeof(RepeatButton), |
|||
typeof(ScrollViewer), |
|||
typeof(Slider), |
|||
typeof(Spinner), |
|||
typeof(SplitView), |
|||
typeof(TextBox), |
|||
typeof(ToggleSwitch), |
|||
typeof(TreeView), |
|||
typeof(Viewbox), |
|||
typeof(Window), |
|||
}; |
|||
|
|||
foreach (var type in types) |
|||
{ |
|||
yield return new Style(x => x.OfType(type)) |
|||
{ |
|||
Setters = { new Setter(Control.TagProperty, type.Name) } |
|||
}; |
|||
|
|||
yield return new Style(x => x.OfType(type).Class("foo")) |
|||
{ |
|||
Setters = { new Setter(Control.TagProperty, type.Name + " foo") } |
|||
}; |
|||
|
|||
yield return new Style(x => x.OfType(type).Class("bar")) |
|||
{ |
|||
Setters = { new Setter(Control.TagProperty, type.Name + " bar") } |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue