From 229c8b7f12762ce4f37c241c13c15e50bde83c1b Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Fri, 29 May 2020 00:36:15 +0200 Subject: [PATCH] Benchmark and simple optimization for INPC accessor. --- .../Plugins/InpcPropertyAccessorPlugin.cs | 8 ++- .../Data/PropertyAccessorBenchmarks.cs | 57 +++++++++++++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 tests/Avalonia.Benchmarks/Data/PropertyAccessorBenchmarks.cs diff --git a/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs index f2ed86d2aa..84ef0fb695 100644 --- a/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs @@ -1,7 +1,5 @@ using System; using System.ComponentModel; -using System.Linq; -using System.Reactive.Linq; using System.Reflection; using Avalonia.Utilities; @@ -31,7 +29,11 @@ namespace Avalonia.Data.Core.Plugins Contract.Requires(propertyName != null); reference.TryGetTarget(out object instance); - var p = instance.GetType().GetRuntimeProperties().FirstOrDefault(x => x.Name == propertyName); + + const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | + BindingFlags.Static | BindingFlags.Instance; + + var p = instance.GetType().GetProperty(propertyName, bindingFlags); if (p != null) { diff --git a/tests/Avalonia.Benchmarks/Data/PropertyAccessorBenchmarks.cs b/tests/Avalonia.Benchmarks/Data/PropertyAccessorBenchmarks.cs new file mode 100644 index 0000000000..5c2502422a --- /dev/null +++ b/tests/Avalonia.Benchmarks/Data/PropertyAccessorBenchmarks.cs @@ -0,0 +1,57 @@ +using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using Avalonia.Data.Core.Plugins; +using BenchmarkDotNet.Attributes; +using JetBrains.Annotations; + +namespace Avalonia.Benchmarks.Data +{ + [MemoryDiagnoser, InProcess] + public class PropertyAccessorBenchmarks + { + private readonly InpcPropertyAccessorPlugin _plugin = new InpcPropertyAccessorPlugin(); + private readonly TestObject _targetStrongRef = new TestObject(); + private readonly WeakReference _targetWeakRef; + + public PropertyAccessorBenchmarks() + { + _targetWeakRef = new WeakReference(_targetStrongRef); + } + + [Benchmark] + public void InpcAccessor() + { + _plugin.Start(_targetWeakRef, nameof(TestObject.Test)); + } + + private class TestObject : INotifyPropertyChanged + { + private string _test; + + public string Test + { + get => _test; + set + { + if (_test == value) + { + return; + } + + _test = value; + + OnPropertyChanged(); + } + } + + public event PropertyChangedEventHandler PropertyChanged; + + [NotifyPropertyChangedInvocator] + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } + } +}