From 4b13d3c04a8e108b03115b1127823089eda96506 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Tue, 17 Mar 2020 21:58:09 +0100 Subject: [PATCH 1/3] Add benchmarks for TextBox and Button. --- ...endarBenchmark.cs => ControlsBenchmark.cs} | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) rename tests/Avalonia.Benchmarks/Layout/{CalendarBenchmark.cs => ControlsBenchmark.cs} (64%) diff --git a/tests/Avalonia.Benchmarks/Layout/CalendarBenchmark.cs b/tests/Avalonia.Benchmarks/Layout/ControlsBenchmark.cs similarity index 64% rename from tests/Avalonia.Benchmarks/Layout/CalendarBenchmark.cs rename to tests/Avalonia.Benchmarks/Layout/ControlsBenchmark.cs index c55912d94d..de40c247e6 100644 --- a/tests/Avalonia.Benchmarks/Layout/CalendarBenchmark.cs +++ b/tests/Avalonia.Benchmarks/Layout/ControlsBenchmark.cs @@ -7,12 +7,12 @@ using BenchmarkDotNet.Attributes; namespace Avalonia.Benchmarks.Layout { [MemoryDiagnoser] - public class CalendarBenchmark : IDisposable + public class ControlsBenchmark : IDisposable { private readonly IDisposable _app; private readonly TestRoot _root; - public CalendarBenchmark() + public ControlsBenchmark() { _app = UnitTestApplication.Start( TestServices.StyledWindow.With( @@ -38,6 +38,28 @@ namespace Avalonia.Benchmarks.Layout _root.LayoutManager.ExecuteLayoutPass(); } + [Benchmark] + [MethodImpl(MethodImplOptions.NoInlining)] + public void CreateButton() + { + var button = new Button(); + + _root.Child = button; + + _root.LayoutManager.ExecuteLayoutPass(); + } + + [Benchmark] + [MethodImpl(MethodImplOptions.NoInlining)] + public void CreateTextBox() + { + var textBox = new TextBox(); + + _root.Child = textBox; + + _root.LayoutManager.ExecuteLayoutPass(); + } + public void Dispose() { _app.Dispose(); From b3a8b39670c06bb25978e9c35555eaacc3952aad Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Tue, 17 Mar 2020 21:58:26 +0100 Subject: [PATCH 2/3] Remove extra allocations from Scrollbar constructor. --- src/Avalonia.Controls/Primitives/ScrollBar.cs | 45 +++++++++---------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/ScrollBar.cs b/src/Avalonia.Controls/Primitives/ScrollBar.cs index 4d3ae3c5b8..982c1cdbfc 100644 --- a/src/Avalonia.Controls/Primitives/ScrollBar.cs +++ b/src/Avalonia.Controls/Primitives/ScrollBar.cs @@ -2,8 +2,6 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; -using System.Reactive; -using System.Reactive.Linq; using Avalonia.Data; using Avalonia.Interactivity; using Avalonia.Input; @@ -57,6 +55,16 @@ namespace Avalonia.Controls.Primitives { Thumb.DragDeltaEvent.AddClassHandler((x, e) => x.OnThumbDragDelta(e), RoutingStrategies.Bubble); Thumb.DragCompletedEvent.AddClassHandler((x, e) => x.OnThumbDragComplete(e), RoutingStrategies.Bubble); + + static void AffectsIsVisible(AvaloniaProperty property) + { + property.Changed.AddClassHandler((x, e) => x.CalculateIsVisible()); + } + + AffectsIsVisible(MinimumProperty); + AffectsIsVisible(MaximumProperty); + AffectsIsVisible(ViewportSizeProperty); + AffectsIsVisible(VisibilityProperty); } /// @@ -64,13 +72,6 @@ namespace Avalonia.Controls.Primitives /// public ScrollBar() { - var isVisible = Observable.Merge( - this.GetObservable(MinimumProperty).Select(_ => Unit.Default), - this.GetObservable(MaximumProperty).Select(_ => Unit.Default), - this.GetObservable(ViewportSizeProperty).Select(_ => Unit.Default), - this.GetObservable(VisibilityProperty).Select(_ => Unit.Default)) - .Select(_ => CalculateIsVisible()); - this.Bind(IsVisibleProperty, isVisible, BindingPriority.Style); UpdatePseudoClasses(Orientation); } @@ -107,24 +108,18 @@ namespace Avalonia.Controls.Primitives /// /// Calculates whether the scrollbar should be visible. /// - /// The scrollbar's visibility. - private bool CalculateIsVisible() + private void CalculateIsVisible() { - switch (Visibility) + var isVisible = Visibility switch { - case ScrollBarVisibility.Visible: - return true; - - case ScrollBarVisibility.Disabled: - case ScrollBarVisibility.Hidden: - return false; - - case ScrollBarVisibility.Auto: - return double.IsNaN(ViewportSize) || Maximum > 0; - - default: - throw new InvalidOperationException("Invalid value for ScrollBar.Visibility."); - } + ScrollBarVisibility.Visible => true, + ScrollBarVisibility.Disabled => false, + ScrollBarVisibility.Hidden => false, + ScrollBarVisibility.Auto => (double.IsNaN(ViewportSize) || Maximum > 0), + _ => throw new InvalidOperationException("Invalid value for ScrollBar.Visibility.") + }; + + SetValue(IsVisibleProperty, isVisible, BindingPriority.Style); } protected override void OnKeyDown(KeyEventArgs e) From 4dd5e08d9e4773ff7913ae25cd098151bc6253e3 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Fri, 27 Mar 2020 15:20:42 +0100 Subject: [PATCH 3/3] Get rid of class handler in favor of OnPropertyChanged. --- src/Avalonia.Controls/Primitives/ScrollBar.cs | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/ScrollBar.cs b/src/Avalonia.Controls/Primitives/ScrollBar.cs index 982c1cdbfc..161c7121c5 100644 --- a/src/Avalonia.Controls/Primitives/ScrollBar.cs +++ b/src/Avalonia.Controls/Primitives/ScrollBar.cs @@ -55,16 +55,6 @@ namespace Avalonia.Controls.Primitives { Thumb.DragDeltaEvent.AddClassHandler((x, e) => x.OnThumbDragDelta(e), RoutingStrategies.Bubble); Thumb.DragCompletedEvent.AddClassHandler((x, e) => x.OnThumbDragComplete(e), RoutingStrategies.Bubble); - - static void AffectsIsVisible(AvaloniaProperty property) - { - property.Changed.AddClassHandler((x, e) => x.CalculateIsVisible()); - } - - AffectsIsVisible(MinimumProperty); - AffectsIsVisible(MaximumProperty); - AffectsIsVisible(ViewportSizeProperty); - AffectsIsVisible(VisibilityProperty); } /// @@ -106,9 +96,9 @@ namespace Avalonia.Controls.Primitives public event EventHandler Scroll; /// - /// Calculates whether the scrollbar should be visible. + /// Calculates and updates whether the scrollbar should be visible. /// - private void CalculateIsVisible() + private void UpdateIsVisible() { var isVisible = Visibility switch { @@ -148,6 +138,16 @@ namespace Avalonia.Controls.Primitives { UpdatePseudoClasses(newValue.GetValueOrDefault()); } + else + { + if (property == MinimumProperty || + property == MaximumProperty || + property == ViewportSizeProperty || + property == VisibilityProperty) + { + UpdateIsVisible(); + } + } } protected override void OnTemplateApplied(TemplateAppliedEventArgs e)