Browse Source

Merge branch 'master' into ContentPresenterTextProps

pull/7956/head
amwx 4 years ago
committed by GitHub
parent
commit
0b845c659c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      tests/Avalonia.Benchmarks/Avalonia.Benchmarks.csproj
  2. 149
      tests/Avalonia.Benchmarks/Base/AvaloniaObject_Binding.cs
  3. 81
      tests/Avalonia.Benchmarks/Base/AvaloniaObject_Construct.cs
  4. 171
      tests/Avalonia.Benchmarks/Base/AvaloniaObject_GetObservable.cs
  5. 181
      tests/Avalonia.Benchmarks/Base/AvaloniaObject_GetValue.cs
  6. 95
      tests/Avalonia.Benchmarks/Base/AvaloniaObject_GetValueInherited.cs
  7. 130
      tests/Avalonia.Benchmarks/Base/AvaloniaObject_SetValue.cs
  8. 14
      tests/Avalonia.Benchmarks/Base/DirectPropertyBenchmark.cs
  9. 65
      tests/Avalonia.Benchmarks/Styling/Style_Activation.cs
  10. 89
      tests/Avalonia.Benchmarks/Styling/Style_Apply.cs
  11. 74
      tests/Avalonia.Benchmarks/Styling/Style_NonActive.cs
  12. 38
      tests/Avalonia.Benchmarks/TestBindingObservable.cs
  13. 112
      tests/Avalonia.Benchmarks/TestTypes.cs

2
tests/Avalonia.Benchmarks/Avalonia.Benchmarks.csproj

@ -19,7 +19,7 @@
<ProjectReference Include="..\Avalonia.UnitTests\Avalonia.UnitTests.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />

149
tests/Avalonia.Benchmarks/Base/AvaloniaObject_Binding.cs

@ -0,0 +1,149 @@
using System.Runtime.CompilerServices;
using Avalonia.Data;
using BenchmarkDotNet.Attributes;
#nullable enable
namespace Avalonia.Benchmarks.Base
{
[MemoryDiagnoser]
public class AvaloniaObject_Binding
{
private static TestClass _target = null!;
private static TestBindingObservable<string?> s_stringSource = new();
private static TestBindingObservable<Struct1> s_struct1Source = new();
private static TestBindingObservable<Struct2> s_struct2Source = new();
private static TestBindingObservable<Struct3> s_struct3Source = new();
private static TestBindingObservable<Struct4> s_struct4Source = new();
private static TestBindingObservable<Struct5> s_struct5Source = new();
private static TestBindingObservable<Struct6> s_struct6Source = new();
private static TestBindingObservable<Struct7> s_struct7Source = new();
private static TestBindingObservable<Struct8> s_struct8Source = new();
public AvaloniaObject_Binding()
{
RuntimeHelpers.RunClassConstructor(typeof(TestClass).TypeHandle);
}
[GlobalSetup]
public void Setup()
{
_target = new TestClass();
}
[Benchmark]
public void Setup_Dispose_LocalValue_Bindings()
{
var target = _target;
for (var i = 0; i < 100; ++i)
{
using var s0 = target.Bind(TestClass.StringProperty, s_stringSource);
using var s1 = target.Bind(TestClass.Struct1Property, s_struct1Source);
using var s2 = target.Bind(TestClass.Struct2Property, s_struct2Source);
using var s3 = target.Bind(TestClass.Struct3Property, s_struct3Source);
using var s4 = target.Bind(TestClass.Struct4Property, s_struct4Source);
using var s5 = target.Bind(TestClass.Struct5Property, s_struct5Source);
using var s6 = target.Bind(TestClass.Struct6Property, s_struct6Source);
using var s7 = target.Bind(TestClass.Struct7Property, s_struct7Source);
using var s8 = target.Bind(TestClass.Struct8Property, s_struct8Source);
}
}
[Benchmark]
public void Fire_LocalValue_Bindings()
{
var target = _target;
using var s0 = target.Bind(TestClass.StringProperty, s_stringSource);
using var s1 = target.Bind(TestClass.Struct1Property, s_struct1Source);
using var s2 = target.Bind(TestClass.Struct2Property, s_struct2Source);
using var s3 = target.Bind(TestClass.Struct3Property, s_struct3Source);
using var s4 = target.Bind(TestClass.Struct4Property, s_struct4Source);
using var s5 = target.Bind(TestClass.Struct5Property, s_struct5Source);
using var s6 = target.Bind(TestClass.Struct6Property, s_struct6Source);
using var s7 = target.Bind(TestClass.Struct7Property, s_struct7Source);
using var s8 = target.Bind(TestClass.Struct8Property, s_struct8Source);
for (var i = 0; i < 100; ++i)
{
s_stringSource.OnNext(i.ToString());
s_struct1Source.OnNext(new(i + 1));
s_struct2Source.OnNext(new(i + 1));
s_struct3Source.OnNext(new(i + 1));
s_struct4Source.OnNext(new(i + 1));
s_struct5Source.OnNext(new(i + 1));
s_struct6Source.OnNext(new(i + 1));
s_struct7Source.OnNext(new(i + 1));
s_struct8Source.OnNext(new(i + 1));
}
}
[GlobalSetup(Target = nameof(Fire_LocalValue_Bindings_With_Style_Values))]
public void SetupStyleValues()
{
_target = new TestClass();
_target.SetValue(TestClass.StringProperty, "foo", BindingPriority.Style);
_target.SetValue(TestClass.Struct1Property, new(), BindingPriority.Style);
_target.SetValue(TestClass.Struct2Property, new(), BindingPriority.Style);
_target.SetValue(TestClass.Struct3Property, new(), BindingPriority.Style);
_target.SetValue(TestClass.Struct4Property, new(), BindingPriority.Style);
_target.SetValue(TestClass.Struct5Property, new(), BindingPriority.Style);
_target.SetValue(TestClass.Struct6Property, new(), BindingPriority.Style);
_target.SetValue(TestClass.Struct7Property, new(), BindingPriority.Style);
_target.SetValue(TestClass.Struct8Property, new(), BindingPriority.Style);
}
[Benchmark]
public void Fire_LocalValue_Bindings_With_Style_Values()
{
var target = _target;
using var s0 = target.Bind(TestClass.StringProperty, s_stringSource);
using var s1 = target.Bind(TestClass.Struct1Property, s_struct1Source);
using var s2 = target.Bind(TestClass.Struct2Property, s_struct2Source);
using var s3 = target.Bind(TestClass.Struct3Property, s_struct3Source);
using var s4 = target.Bind(TestClass.Struct4Property, s_struct4Source);
using var s5 = target.Bind(TestClass.Struct5Property, s_struct5Source);
using var s6 = target.Bind(TestClass.Struct6Property, s_struct6Source);
using var s7 = target.Bind(TestClass.Struct7Property, s_struct7Source);
using var s8 = target.Bind(TestClass.Struct8Property, s_struct8Source);
for (var i = 0; i < 100; ++i)
{
s_stringSource.OnNext(i.ToString());
s_struct1Source.OnNext(new(i + 1));
s_struct2Source.OnNext(new(i + 1));
s_struct3Source.OnNext(new(i + 1));
s_struct4Source.OnNext(new(i + 1));
s_struct5Source.OnNext(new(i + 1));
s_struct6Source.OnNext(new(i + 1));
s_struct7Source.OnNext(new(i + 1));
s_struct8Source.OnNext(new(i + 1));
}
}
private class TestClass : AvaloniaObject
{
public static readonly StyledProperty<string?> StringProperty =
AvaloniaProperty.Register<TestClass, string?>("String");
public static readonly StyledProperty<Struct1> Struct1Property =
AvaloniaProperty.Register<TestClass, Struct1>("Struct1");
public static readonly StyledProperty<Struct2> Struct2Property =
AvaloniaProperty.Register<TestClass, Struct2>("Struct2");
public static readonly StyledProperty<Struct3> Struct3Property =
AvaloniaProperty.Register<TestClass, Struct3>("Struct3");
public static readonly StyledProperty<Struct4> Struct4Property =
AvaloniaProperty.Register<TestClass, Struct4>("Struct4");
public static readonly StyledProperty<Struct5> Struct5Property =
AvaloniaProperty.Register<TestClass, Struct5>("Struct5");
public static readonly StyledProperty<Struct6> Struct6Property =
AvaloniaProperty.Register<TestClass, Struct6>("Struct6");
public static readonly StyledProperty<Struct7> Struct7Property =
AvaloniaProperty.Register<TestClass, Struct7>("Struct7");
public static readonly StyledProperty<Struct8> Struct8Property =
AvaloniaProperty.Register<TestClass, Struct8>("Struct8");
}
}
}

81
tests/Avalonia.Benchmarks/Base/AvaloniaObject_Construct.cs

@ -0,0 +1,81 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
#nullable enable
namespace Avalonia.Benchmarks.Base
{
[MemoryDiagnoser]
public class AvaloniaObject_Construct
{
public AvaloniaObject_Construct()
{
RuntimeHelpers.RunClassConstructor(typeof(TestClass).TypeHandle);
}
[Benchmark(Baseline = true)]
public void ConstructClrObject_And_Set_Values()
{
var target = new BaselineTestClass();
target.StringProperty = "foo";
target.Struct1Property = new(1);
target.Struct2Property = new(1);
target.Struct3Property = new(1);
target.Struct4Property = new(1);
target.Struct5Property = new(1);
target.Struct6Property = new(1);
target.Struct7Property = new(1);
target.Struct8Property = new(1);
}
[Benchmark]
public void Construct_And_Set_Values()
{
var target = new TestClass();
target.SetValue(TestClass.StringProperty, "foo");
target.SetValue(TestClass.Struct1Property, new(1));
target.SetValue(TestClass.Struct2Property, new(1));
target.SetValue(TestClass.Struct3Property, new(1));
target.SetValue(TestClass.Struct4Property, new(1));
target.SetValue(TestClass.Struct5Property, new(1));
target.SetValue(TestClass.Struct6Property, new(1));
target.SetValue(TestClass.Struct7Property, new(1));
target.SetValue(TestClass.Struct8Property, new(1));
}
private class TestClass : AvaloniaObject
{
public static readonly StyledProperty<string> StringProperty =
AvaloniaProperty.Register<TestClass, string>("String");
public static readonly StyledProperty<Struct1> Struct1Property =
AvaloniaProperty.Register<TestClass, Struct1>("Struct1");
public static readonly StyledProperty<Struct2> Struct2Property =
AvaloniaProperty.Register<TestClass, Struct2>("Struct2");
public static readonly StyledProperty<Struct3> Struct3Property =
AvaloniaProperty.Register<TestClass, Struct3>("Struct3");
public static readonly StyledProperty<Struct4> Struct4Property =
AvaloniaProperty.Register<TestClass, Struct4>("Struct4");
public static readonly StyledProperty<Struct5> Struct5Property =
AvaloniaProperty.Register<TestClass, Struct5>("Struct5");
public static readonly StyledProperty<Struct6> Struct6Property =
AvaloniaProperty.Register<TestClass, Struct6>("Struct6");
public static readonly StyledProperty<Struct7> Struct7Property =
AvaloniaProperty.Register<TestClass, Struct7>("Struct7");
public static readonly StyledProperty<Struct8> Struct8Property =
AvaloniaProperty.Register<TestClass, Struct8>("Struct8");
}
private class BaselineTestClass
{
public string? StringProperty { get; set; }
public Struct1 Struct1Property { get; set; }
public Struct2 Struct2Property { get; set; }
public Struct3 Struct3Property { get; set; }
public Struct4 Struct4Property { get; set; }
public Struct5 Struct5Property { get; set; }
public Struct6 Struct6Property { get; set; }
public Struct7 Struct7Property { get; set; }
public Struct8 Struct8Property { get; set; }
}
}
}

171
tests/Avalonia.Benchmarks/Base/AvaloniaObject_GetObservable.cs

@ -0,0 +1,171 @@
using System;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
#nullable enable
namespace Avalonia.Benchmarks.Base
{
[MemoryDiagnoser]
public class AvaloniaObject_GetObservable
{
private TestClass _target = null!;
public static int result;
public AvaloniaObject_GetObservable()
{
RuntimeHelpers.RunClassConstructor(typeof(TestClass).TypeHandle);
}
[GlobalSetup]
public void Setup()
{
_target = new();
}
[Benchmark(Baseline = true)]
public void PropertyChangedSubscription()
{
var target = _target;
static void ChangeHandler(object? sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.Property == TestClass.StringProperty)
{
var ev = (AvaloniaPropertyChangedEventArgs<string?>)e;
result += ev.NewValue.Value?.Length ?? 0;
}
else if (e.Property == TestClass.Struct1Property)
{
var ev = (AvaloniaPropertyChangedEventArgs<Struct1>)e;
result += ev.NewValue.Value.Int1;
}
else if (e.Property == TestClass.Struct2Property)
{
var ev = (AvaloniaPropertyChangedEventArgs<Struct2>)e;
result += ev.NewValue.Value.Int1;
}
else if (e.Property == TestClass.Struct3Property)
{
var ev = (AvaloniaPropertyChangedEventArgs<Struct3>)e;
result += ev.NewValue.Value.Int1;
}
else if (e.Property == TestClass.Struct4Property)
{
var ev = (AvaloniaPropertyChangedEventArgs<Struct4>)e;
result += ev.NewValue.Value.Int1;
}
else if (e.Property == TestClass.Struct5Property)
{
var ev = (AvaloniaPropertyChangedEventArgs<Struct5>)e;
result += ev.NewValue.Value.Int1;
}
else if (e.Property == TestClass.Struct6Property)
{
var ev = (AvaloniaPropertyChangedEventArgs<Struct6>)e;
result += ev.NewValue.Value.Int1;
}
else if (e.Property == TestClass.Struct7Property)
{
var ev = (AvaloniaPropertyChangedEventArgs<Struct7>)e;
result += ev.NewValue.Value.Int1;
}
else if (e.Property == TestClass.Struct8Property)
{
var ev = (AvaloniaPropertyChangedEventArgs<Struct8>)e;
result += ev.NewValue.Value.Int1;
}
}
target.PropertyChanged += ChangeHandler;
// GetObservable fires with the initial value so to compare like-for-like we also need
// to get the initial value here.
result += target.GetValue(TestClass.StringProperty)?.Length ?? 0;
result += target.GetValue(TestClass.Struct1Property).Int1;
result += target.GetValue(TestClass.Struct2Property).Int1;
result += target.GetValue(TestClass.Struct3Property).Int1;
result += target.GetValue(TestClass.Struct4Property).Int1;
result += target.GetValue(TestClass.Struct5Property).Int1;
result += target.GetValue(TestClass.Struct6Property).Int1;
result += target.GetValue(TestClass.Struct7Property).Int1;
result += target.GetValue(TestClass.Struct8Property).Int1;
for (var i = 0; i < 100; ++i)
{
target.SetValue(TestClass.StringProperty, "foo" + i);
target.SetValue(TestClass.Struct1Property, new(i + 1));
target.SetValue(TestClass.Struct2Property, new(i + 1));
target.SetValue(TestClass.Struct3Property, new(i + 1));
target.SetValue(TestClass.Struct4Property, new(i + 1));
target.SetValue(TestClass.Struct5Property, new(i + 1));
target.SetValue(TestClass.Struct6Property, new(i + 1));
target.SetValue(TestClass.Struct7Property, new(i + 1));
target.SetValue(TestClass.Struct8Property, new(i + 1));
}
target.PropertyChanged -= ChangeHandler;
}
[Benchmark]
public void GetObservables()
{
var target = _target;
var sub1 = target.GetObservable(TestClass.StringProperty).Subscribe(x => result += x?.Length ?? 0);
var sub2 = target.GetObservable(TestClass.Struct1Property).Subscribe(x => result += x.Int1);
var sub3 = target.GetObservable(TestClass.Struct2Property).Subscribe(x => result += x.Int1);
var sub4 = target.GetObservable(TestClass.Struct3Property).Subscribe(x => result += x.Int1);
var sub5 = target.GetObservable(TestClass.Struct4Property).Subscribe(x => result += x.Int1);
var sub6 = target.GetObservable(TestClass.Struct5Property).Subscribe(x => result += x.Int1);
var sub7 = target.GetObservable(TestClass.Struct6Property).Subscribe(x => result += x.Int1);
var sub8 = target.GetObservable(TestClass.Struct7Property).Subscribe(x => result += x.Int1);
var sub9 = target.GetObservable(TestClass.Struct8Property).Subscribe(x => result += x.Int1);
for (var i = 0; i < 100; ++i)
{
target.SetValue(TestClass.StringProperty, "foo" + i);
target.SetValue(TestClass.Struct1Property, new(i + 1));
target.SetValue(TestClass.Struct2Property, new(i + 1));
target.SetValue(TestClass.Struct3Property, new(i + 1));
target.SetValue(TestClass.Struct4Property, new(i + 1));
target.SetValue(TestClass.Struct5Property, new(i + 1));
target.SetValue(TestClass.Struct6Property, new(i + 1));
target.SetValue(TestClass.Struct7Property, new(i + 1));
target.SetValue(TestClass.Struct8Property, new(i + 1));
}
sub1.Dispose();
sub2.Dispose();
sub3.Dispose();
sub4.Dispose();
sub5.Dispose();
sub6.Dispose();
sub7.Dispose();
sub8.Dispose();
sub9.Dispose();
}
private class TestClass : AvaloniaObject
{
public static readonly StyledProperty<string> StringProperty =
AvaloniaProperty.Register<TestClass, string>("String");
public static readonly StyledProperty<Struct1> Struct1Property =
AvaloniaProperty.Register<TestClass, Struct1>("Struct1");
public static readonly StyledProperty<Struct2> Struct2Property =
AvaloniaProperty.Register<TestClass, Struct2>("Struct2");
public static readonly StyledProperty<Struct3> Struct3Property =
AvaloniaProperty.Register<TestClass, Struct3>("Struct3");
public static readonly StyledProperty<Struct4> Struct4Property =
AvaloniaProperty.Register<TestClass, Struct4>("Struct4");
public static readonly StyledProperty<Struct5> Struct5Property =
AvaloniaProperty.Register<TestClass, Struct5>("Struct5");
public static readonly StyledProperty<Struct6> Struct6Property =
AvaloniaProperty.Register<TestClass, Struct6>("Struct6");
public static readonly StyledProperty<Struct7> Struct7Property =
AvaloniaProperty.Register<TestClass, Struct7>("Struct7");
public static readonly StyledProperty<Struct8> Struct8Property =
AvaloniaProperty.Register<TestClass, Struct8>("Struct8");
}
}
}

181
tests/Avalonia.Benchmarks/Base/AvaloniaObject_GetValue.cs

@ -0,0 +1,181 @@
using System.Runtime.CompilerServices;
using Avalonia.Data;
using BenchmarkDotNet.Attributes;
#nullable enable
namespace Avalonia.Benchmarks.Base
{
[MemoryDiagnoser]
public class AvaloniaObject_GetValue
{
private BaselineTestClass _baseline = new(){ StringProperty = "foo" };
private TestClass _target = new();
public AvaloniaObject_GetValue()
{
RuntimeHelpers.RunClassConstructor(typeof(TestClass).TypeHandle);
}
[Benchmark(Baseline = true)]
public int GetClrPropertyValues()
{
var target = _baseline;
var result = 0;
for (var i = 0; i < 100; ++i)
{
result += target.StringProperty?.Length ?? 0;
result += target.Struct1Property.Int1;
result += target.Struct2Property.Int1;
result += target.Struct3Property.Int1;
result += target.Struct4Property.Int1;
result += target.Struct5Property.Int1;
result += target.Struct6Property.Int1;
result += target.Struct7Property.Int1;
result += target.Struct8Property.Int1;
}
return result;
}
[Benchmark]
public int GetDefaultValues()
{
var target = _target;
var result = 0;
for (var i = 0; i < 100; ++i)
{
result += target.GetValue(TestClass.StringProperty)?.Length ?? 0;
result += target.GetValue(TestClass.Struct1Property).Int1;
result += target.GetValue(TestClass.Struct2Property).Int1;
result += target.GetValue(TestClass.Struct3Property).Int1;
result += target.GetValue(TestClass.Struct4Property).Int1;
result += target.GetValue(TestClass.Struct5Property).Int1;
result += target.GetValue(TestClass.Struct6Property).Int1;
result += target.GetValue(TestClass.Struct7Property).Int1;
result += target.GetValue(TestClass.Struct8Property).Int1;
}
return result;
}
[GlobalSetup(Target = nameof(Get_Local_Values))]
public void SetupLocalValues()
{
_target.SetValue(TestClass.StringProperty, "foo");
_target.SetValue(TestClass.Struct1Property, new(1));
_target.SetValue(TestClass.Struct2Property, new(1));
_target.SetValue(TestClass.Struct3Property, new(1));
_target.SetValue(TestClass.Struct4Property, new(1));
_target.SetValue(TestClass.Struct5Property, new(1));
_target.SetValue(TestClass.Struct6Property, new(1));
_target.SetValue(TestClass.Struct7Property, new(1));
_target.SetValue(TestClass.Struct8Property, new(1));
}
[Benchmark]
public int Get_Local_Values()
{
var target = _target;
var result = 0;
for (var i = 0; i < 100; ++i)
{
result += target.GetValue(TestClass.StringProperty)?.Length ?? 0;
result += target.GetValue(TestClass.Struct1Property).Int1;
result += target.GetValue(TestClass.Struct2Property).Int1;
result += target.GetValue(TestClass.Struct3Property).Int1;
result += target.GetValue(TestClass.Struct4Property).Int1;
result += target.GetValue(TestClass.Struct5Property).Int1;
result += target.GetValue(TestClass.Struct6Property).Int1;
result += target.GetValue(TestClass.Struct7Property).Int1;
result += target.GetValue(TestClass.Struct8Property).Int1;
}
return result;
}
[GlobalSetup(Target = nameof(Get_Local_Values_With_Style_Values))]
public void SetupLocalValuesAndStyleValues()
{
var target = _target;
target.SetValue(TestClass.StringProperty, "foo");
target.SetValue(TestClass.Struct1Property, new(1));
target.SetValue(TestClass.Struct2Property, new(1));
target.SetValue(TestClass.Struct3Property, new(1));
target.SetValue(TestClass.Struct4Property, new(1));
target.SetValue(TestClass.Struct5Property, new(1));
target.SetValue(TestClass.Struct6Property, new(1));
target.SetValue(TestClass.Struct7Property, new(1));
target.SetValue(TestClass.Struct8Property, new(1));
target.SetValue(TestClass.StringProperty, "bar", BindingPriority.Style);
target.SetValue(TestClass.Struct1Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct2Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct3Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct4Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct5Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct6Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct7Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct8Property, new(), BindingPriority.Style);
}
[Benchmark]
public int Get_Local_Values_With_Style_Values()
{
var target = _target;
var result = 0;
for (var i = 0; i < 100; ++i)
{
result += target.GetValue(TestClass.StringProperty)?.Length ?? 0;
result += target.GetValue(TestClass.Struct1Property).Int1;
result += target.GetValue(TestClass.Struct2Property).Int1;
result += target.GetValue(TestClass.Struct3Property).Int1;
result += target.GetValue(TestClass.Struct4Property).Int1;
result += target.GetValue(TestClass.Struct5Property).Int1;
result += target.GetValue(TestClass.Struct6Property).Int1;
result += target.GetValue(TestClass.Struct7Property).Int1;
result += target.GetValue(TestClass.Struct8Property).Int1;
}
return result;
}
private class TestClass : AvaloniaObject
{
public static readonly StyledProperty<string> StringProperty =
AvaloniaProperty.Register<TestClass, string>("String");
public static readonly StyledProperty<Struct1> Struct1Property =
AvaloniaProperty.Register<TestClass, Struct1>("Struct1");
public static readonly StyledProperty<Struct2> Struct2Property =
AvaloniaProperty.Register<TestClass, Struct2>("Struct2");
public static readonly StyledProperty<Struct3> Struct3Property =
AvaloniaProperty.Register<TestClass, Struct3>("Struct3");
public static readonly StyledProperty<Struct4> Struct4Property =
AvaloniaProperty.Register<TestClass, Struct4>("Struct4");
public static readonly StyledProperty<Struct5> Struct5Property =
AvaloniaProperty.Register<TestClass, Struct5>("Struct5");
public static readonly StyledProperty<Struct6> Struct6Property =
AvaloniaProperty.Register<TestClass, Struct6>("Struct6");
public static readonly StyledProperty<Struct7> Struct7Property =
AvaloniaProperty.Register<TestClass, Struct7>("Struct7");
public static readonly StyledProperty<Struct8> Struct8Property =
AvaloniaProperty.Register<TestClass, Struct8>("Struct8");
}
private class BaselineTestClass
{
public string? StringProperty { get; set; }
public Struct1 Struct1Property { get; set; }
public Struct2 Struct2Property { get; set; }
public Struct3 Struct3Property { get; set; }
public Struct4 Struct4Property { get; set; }
public Struct5 Struct5Property { get; set; }
public Struct6 Struct6Property { get; set; }
public Struct7 Struct7Property { get; set; }
public Struct8 Struct8Property { get; set; }
}
}
}

95
tests/Avalonia.Benchmarks/Base/AvaloniaObject_GetValueInherited.cs

@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Avalonia.Controls;
using BenchmarkDotNet.Attributes;
#nullable enable
namespace Avalonia.Benchmarks.Base
{
[MemoryDiagnoser]
public class AvaloniaObject_GetValueInherited
{
private TestClass _root = null!;
private TestClass _target = null!;
public AvaloniaObject_GetValueInherited()
{
RuntimeHelpers.RunClassConstructor(typeof(TestClass).TypeHandle);
}
[Params(1, 2, 10, 50, 100, 200)]
public int Depth { get; set; }
[GlobalSetup]
public void Setup()
{
_root = new();
_root.SetValue(TestClass.StringProperty, "foo");
_root.SetValue(TestClass.Struct1Property, new(1));
_root.SetValue(TestClass.Struct2Property, new(1));
_root.SetValue(TestClass.Struct3Property, new(1));
_root.SetValue(TestClass.Struct4Property, new(1));
_root.SetValue(TestClass.Struct5Property, new(1));
_root.SetValue(TestClass.Struct6Property, new(1));
_root.SetValue(TestClass.Struct7Property, new(1));
_root.SetValue(TestClass.Struct8Property, new(1));
var parent = _root;
for (var i = 0; i < Depth; ++i)
{
var c = new TestClass();
((ISetLogicalParent)c).SetParent(parent);
parent = c;
}
_target = parent;
}
[Benchmark]
public int GetInheritedValues()
{
var target = _target;
var result = 0;
for (var i = 0; i < 100; ++i)
{
result += target.GetValue(TestClass.StringProperty)?.Length ?? 0;
result += target.GetValue(TestClass.Struct1Property).Int1;
result += target.GetValue(TestClass.Struct2Property).Int1;
result += target.GetValue(TestClass.Struct3Property).Int1;
result += target.GetValue(TestClass.Struct4Property).Int1;
result += target.GetValue(TestClass.Struct5Property).Int1;
result += target.GetValue(TestClass.Struct6Property).Int1;
result += target.GetValue(TestClass.Struct7Property).Int1;
result += target.GetValue(TestClass.Struct8Property).Int1;
}
return result;
}
private class TestClass : Control
{
public static readonly StyledProperty<string> StringProperty =
AvaloniaProperty.Register<TestClass, string>("String", inherits: true);
public static readonly StyledProperty<Struct1> Struct1Property =
AvaloniaProperty.Register<TestClass, Struct1>("Struct1", inherits: true);
public static readonly StyledProperty<Struct2> Struct2Property =
AvaloniaProperty.Register<TestClass, Struct2>("Struct2", inherits: true);
public static readonly StyledProperty<Struct3> Struct3Property =
AvaloniaProperty.Register<TestClass, Struct3>("Struct3", inherits: true);
public static readonly StyledProperty<Struct4> Struct4Property =
AvaloniaProperty.Register<TestClass, Struct4>("Struct4", inherits: true);
public static readonly StyledProperty<Struct5> Struct5Property =
AvaloniaProperty.Register<TestClass, Struct5>("Struct5", inherits: true);
public static readonly StyledProperty<Struct6> Struct6Property =
AvaloniaProperty.Register<TestClass, Struct6>("Struct6", inherits: true);
public static readonly StyledProperty<Struct7> Struct7Property =
AvaloniaProperty.Register<TestClass, Struct7>("Struct7", inherits: true);
public static readonly StyledProperty<Struct8> Struct8Property =
AvaloniaProperty.Register<TestClass, Struct8>("Struct8", inherits: true);
}
}
}

130
tests/Avalonia.Benchmarks/Base/AvaloniaObject_SetValue.cs

@ -0,0 +1,130 @@
using System.Runtime.CompilerServices;
using Avalonia.Data;
using BenchmarkDotNet.Attributes;
#nullable enable
namespace Avalonia.Benchmarks.Base
{
[MemoryDiagnoser]
public class AvaloniaObject_SetValue
{
private BaselineTestClass _baseline = new();
private TestClass _target = new();
public AvaloniaObject_SetValue()
{
RuntimeHelpers.RunClassConstructor(typeof(TestClass).TypeHandle);
}
[Benchmark(Baseline = true)]
public int SetClrPropertyValues()
{
var target = _baseline;
var result = 0;
for (var i = 0; i < 100; ++i)
{
target.StringProperty = "foo";
target.Struct1Property = new(i + 1);
target.Struct2Property = new(i + 1);
target.Struct3Property = new(i + 1);
target.Struct4Property = new(i + 1);
target.Struct5Property = new(i + 1);
target.Struct6Property = new(i + 1);
target.Struct7Property = new(i + 1);
target.Struct8Property = new(i + 1);
}
return result;
}
[Benchmark]
public void SetValues()
{
var target = _target;
for (var i = 0; i < 100; ++i)
{
target.SetValue(TestClass.StringProperty, "foo");
target.SetValue(TestClass.Struct1Property, new(i + 1));
target.SetValue(TestClass.Struct2Property, new(i + 1));
target.SetValue(TestClass.Struct3Property, new(i + 1));
target.SetValue(TestClass.Struct4Property, new(i + 1));
target.SetValue(TestClass.Struct5Property, new(i + 1));
target.SetValue(TestClass.Struct6Property, new(i + 1));
target.SetValue(TestClass.Struct7Property, new(i + 1));
target.SetValue(TestClass.Struct8Property, new(i + 1));
}
}
[GlobalSetup(Target = nameof(Set_Local_Values_With_Style_Values))]
public void SetupStyleValues()
{
var target = _target;
target.SetValue(TestClass.StringProperty, "foo", BindingPriority.Style);
target.SetValue(TestClass.Struct1Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct2Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct3Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct4Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct5Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct6Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct7Property, new(), BindingPriority.Style);
target.SetValue(TestClass.Struct8Property, new(), BindingPriority.Style);
}
[Benchmark]
public void Set_Local_Values_With_Style_Values()
{
var target = _target;
for (var i = 0; i < 100; ++i)
{
target.SetValue(TestClass.StringProperty, "foo");
target.SetValue(TestClass.Struct1Property, new(i + 1));
target.SetValue(TestClass.Struct2Property, new(i + 1));
target.SetValue(TestClass.Struct3Property, new(i + 1));
target.SetValue(TestClass.Struct4Property, new(i + 1));
target.SetValue(TestClass.Struct5Property, new(i + 1));
target.SetValue(TestClass.Struct6Property, new(i + 1));
target.SetValue(TestClass.Struct7Property, new(i + 1));
target.SetValue(TestClass.Struct8Property, new(i + 1));
}
}
private class TestClass : AvaloniaObject
{
public static readonly StyledProperty<string> StringProperty =
AvaloniaProperty.Register<TestClass, string>("String");
public static readonly StyledProperty<Struct1> Struct1Property =
AvaloniaProperty.Register<TestClass, Struct1>("Struct1");
public static readonly StyledProperty<Struct2> Struct2Property =
AvaloniaProperty.Register<TestClass, Struct2>("Struct2");
public static readonly StyledProperty<Struct3> Struct3Property =
AvaloniaProperty.Register<TestClass, Struct3>("Struct3");
public static readonly StyledProperty<Struct4> Struct4Property =
AvaloniaProperty.Register<TestClass, Struct4>("Struct4");
public static readonly StyledProperty<Struct5> Struct5Property =
AvaloniaProperty.Register<TestClass, Struct5>("Struct5");
public static readonly StyledProperty<Struct6> Struct6Property =
AvaloniaProperty.Register<TestClass, Struct6>("Struct6");
public static readonly StyledProperty<Struct7> Struct7Property =
AvaloniaProperty.Register<TestClass, Struct7>("Struct7");
public static readonly StyledProperty<Struct8> Struct8Property =
AvaloniaProperty.Register<TestClass, Struct8>("Struct8");
}
private class BaselineTestClass
{
public string? StringProperty { get; set; }
public Struct1 Struct1Property { get; set; }
public Struct2 Struct2Property { get; set; }
public Struct3 Struct3Property { get; set; }
public Struct4 Struct4Property { get; set; }
public Struct5 Struct5Property { get; set; }
public Struct6 Struct6Property { get; set; }
public Struct7 Struct7Property { get; set; }
public Struct8 Struct8Property { get; set; }
}
}
}

14
tests/Avalonia.Benchmarks/Base/DirectPropertyBenchmark.cs

@ -1,14 +1,22 @@
using BenchmarkDotNet.Attributes;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
namespace Avalonia.Benchmarks.Base
{
[MemoryDiagnoser]
public class DirectPropertyBenchmark
{
private DirectClass _target = new();
public DirectPropertyBenchmark()
{
RuntimeHelpers.RunClassConstructor(typeof(DirectClass).TypeHandle);
}
[Benchmark(Baseline = true)]
public void SetAndRaiseOriginal()
{
var obj = new DirectClass();
var obj = _target;
for (var i = 0; i < 100; ++i)
{
@ -19,7 +27,7 @@ namespace Avalonia.Benchmarks.Base
[Benchmark]
public void SetAndRaiseSimple()
{
var obj = new DirectClass();
var obj = _target;
for (var i = 0; i < 100; ++i)
{

65
tests/Avalonia.Benchmarks/Styling/Style_Activation.cs

@ -0,0 +1,65 @@
using System.Runtime.CompilerServices;
using Avalonia.Controls;
using Avalonia.Styling;
using BenchmarkDotNet.Attributes;
#nullable enable
namespace Avalonia.Benchmarks.Styling
{
[MemoryDiagnoser]
public class Style_Activation
{
private TestClass _target = null!;
public Style_Activation()
{
RuntimeHelpers.RunClassConstructor(typeof(TestClass).TypeHandle);
}
[GlobalSetup]
public void Setup()
{
_target = new TestClass();
var style = new Style(x => x.OfType<TestClass>().Class("foo"))
{
Setters = { new Setter(TestClass.StringProperty, "foo") }
};
style.TryAttach(_target, null);
}
[Benchmark]
public void Toggle_Style_Activation_Via_Class()
{
for (var i = 0; i < 100; ++i)
{
_target.Classes.Add("foo");
_target.Classes.Remove("foo");
}
}
private class TestClass : Control
{
public static readonly StyledProperty<string?> StringProperty =
AvaloniaProperty.Register<TestClass, string?>("String");
public static readonly StyledProperty<Struct1> Struct1Property =
AvaloniaProperty.Register<TestClass, Struct1>("Struct1");
public static readonly StyledProperty<Struct2> Struct2Property =
AvaloniaProperty.Register<TestClass, Struct2>("Struct2");
public static readonly StyledProperty<Struct3> Struct3Property =
AvaloniaProperty.Register<TestClass, Struct3>("Struct3");
public static readonly StyledProperty<Struct4> Struct4Property =
AvaloniaProperty.Register<TestClass, Struct4>("Struct4");
public static readonly StyledProperty<Struct5> Struct5Property =
AvaloniaProperty.Register<TestClass, Struct5>("Struct5");
public static readonly StyledProperty<Struct6> Struct6Property =
AvaloniaProperty.Register<TestClass, Struct6>("Struct6");
public static readonly StyledProperty<Struct7> Struct7Property =
AvaloniaProperty.Register<TestClass, Struct7>("Struct7");
public static readonly StyledProperty<Struct8> Struct8Property =
AvaloniaProperty.Register<TestClass, Struct8>("Struct8");
}
}
}

89
tests/Avalonia.Benchmarks/Styling/Style_Apply.cs

@ -0,0 +1,89 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Avalonia.Controls;
using Avalonia.Styling;
using BenchmarkDotNet.Attributes;
#nullable enable
namespace Avalonia.Benchmarks.Styling
{
[MemoryDiagnoser]
public class Style_Apply
{
private List<Style> _styles = new();
public Style_Apply()
{
RuntimeHelpers.RunClassConstructor(typeof(TestClass).TypeHandle);
}
[Params(1, 5, 50)]
public int MatchingStyles { get; set; }
[Params(1, 5, 50)]
public int NonMatchingStyles { get; set; }
[GlobalSetup]
public void Setup()
{
_styles.Clear();
for (var i = 0; i < MatchingStyles; ++i)
{
_styles.Add(new Style(x => x.OfType<TestClass>())
{
Setters = { new Setter(TestClass.StringProperty, "foo") }
});
}
for (var i = 0; i < NonMatchingStyles; ++i)
{
_styles.Add(new Style(x => x.OfType<TestClass2>().Class("missing"))
{
Setters = { new Setter(TestClass.StringProperty, "foo") }
});
}
}
[Benchmark]
public void Apply_Simple_Styles()
{
var target = new TestClass();
target.BeginBatchUpdate();
foreach (var style in _styles)
style.TryAttach(target, null);
target.EndBatchUpdate();
}
private class TestClass : Control
{
public static readonly StyledProperty<string?> StringProperty =
AvaloniaProperty.Register<TestClass, string?>("String");
public static readonly StyledProperty<Struct1> Struct1Property =
AvaloniaProperty.Register<TestClass, Struct1>("Struct1");
public static readonly StyledProperty<Struct2> Struct2Property =
AvaloniaProperty.Register<TestClass, Struct2>("Struct2");
public static readonly StyledProperty<Struct3> Struct3Property =
AvaloniaProperty.Register<TestClass, Struct3>("Struct3");
public static readonly StyledProperty<Struct4> Struct4Property =
AvaloniaProperty.Register<TestClass, Struct4>("Struct4");
public static readonly StyledProperty<Struct5> Struct5Property =
AvaloniaProperty.Register<TestClass, Struct5>("Struct5");
public static readonly StyledProperty<Struct6> Struct6Property =
AvaloniaProperty.Register<TestClass, Struct6>("Struct6");
public static readonly StyledProperty<Struct7> Struct7Property =
AvaloniaProperty.Register<TestClass, Struct7>("Struct7");
public static readonly StyledProperty<Struct8> Struct8Property =
AvaloniaProperty.Register<TestClass, Struct8>("Struct8");
}
private class TestClass2 : Control
{
}
}
}

74
tests/Avalonia.Benchmarks/Styling/Style_NonActive.cs

@ -0,0 +1,74 @@
using System.Runtime.CompilerServices;
using Avalonia.Controls;
using Avalonia.Styling;
using BenchmarkDotNet.Attributes;
#nullable enable
namespace Avalonia.Benchmarks.Styling
{
[MemoryDiagnoser]
public class Style_NonActive
{
private TestClass _target = null!;
public Style_NonActive()
{
RuntimeHelpers.RunClassConstructor(typeof(TestClass).TypeHandle);
}
[GlobalSetup]
public void Setup()
{
_target = new TestClass();
var style = new Style(x => x.OfType<TestClass>().Class("foo"))
{
Setters = { new Setter(TestClass.StringProperty, "foo") }
};
style.TryAttach(_target, null);
_target.SetValue(TestClass.StringProperty, "foo");
_target.SetValue(TestClass.Struct1Property, new(1));
_target.SetValue(TestClass.Struct2Property, new(1));
_target.SetValue(TestClass.Struct3Property, new(1));
_target.SetValue(TestClass.Struct4Property, new(1));
_target.SetValue(TestClass.Struct5Property, new(1));
_target.SetValue(TestClass.Struct6Property, new(1));
_target.SetValue(TestClass.Struct7Property, new(1));
_target.SetValue(TestClass.Struct8Property, new(1));
}
[Benchmark]
public void Toggle_NonActive_Style_Activation()
{
for (var i = 0; i < 100; ++i)
{
_target.Classes.Add("foo");
_target.Classes.Remove("foo");
}
}
private class TestClass : Control
{
public static readonly StyledProperty<string?> StringProperty =
AvaloniaProperty.Register<TestClass, string?>("String");
public static readonly StyledProperty<Struct1> Struct1Property =
AvaloniaProperty.Register<TestClass, Struct1>("Struct1");
public static readonly StyledProperty<Struct2> Struct2Property =
AvaloniaProperty.Register<TestClass, Struct2>("Struct2");
public static readonly StyledProperty<Struct3> Struct3Property =
AvaloniaProperty.Register<TestClass, Struct3>("Struct3");
public static readonly StyledProperty<Struct4> Struct4Property =
AvaloniaProperty.Register<TestClass, Struct4>("Struct4");
public static readonly StyledProperty<Struct5> Struct5Property =
AvaloniaProperty.Register<TestClass, Struct5>("Struct5");
public static readonly StyledProperty<Struct6> Struct6Property =
AvaloniaProperty.Register<TestClass, Struct6>("Struct6");
public static readonly StyledProperty<Struct7> Struct7Property =
AvaloniaProperty.Register<TestClass, Struct7>("Struct7");
public static readonly StyledProperty<Struct8> Struct8Property =
AvaloniaProperty.Register<TestClass, Struct8>("Struct8");
}
}
}

38
tests/Avalonia.Benchmarks/TestBindingObservable.cs

@ -0,0 +1,38 @@
using System;
using Avalonia.Data;
namespace Avalonia.Benchmarks
{
internal class TestBindingObservable<T> : IObservable<BindingValue<T?>>, IDisposable
{
private T? _value;
private IObserver<BindingValue<T?>>? _observer;
public TestBindingObservable(T? initialValue = default) => _value = initialValue;
public IDisposable Subscribe(IObserver<BindingValue<T?>> observer)
{
if (_observer is object)
throw new InvalidOperationException("The observable can only be subscribed once.");
_observer = observer;
observer.OnNext(_value);
return this;
}
public void Dispose() => _observer = null;
public void OnNext(T? value) => _observer?.OnNext(value);
public void PublishCompleted()
{
_observer?.OnCompleted();
_observer = null;
}
protected void PublishError(Exception error)
{
_observer?.OnError(error);
_observer = null;
}
}
}

112
tests/Avalonia.Benchmarks/TestTypes.cs

@ -0,0 +1,112 @@
using System;
namespace Avalonia.Benchmarks
{
internal record struct Struct1
{
public Struct1(int value)
{
Int1 = value;
}
public int Int1;
}
internal record struct Struct2
{
public Struct2(int value)
{
Int1 = Int2 = value;
}
public int Int1;
public int Int2;
}
internal record struct Struct3
{
public Struct3(int value)
{
Int1 = Int2 = Int3 = value;
}
public int Int1;
public int Int2;
public int Int3;
}
internal record struct Struct4
{
public Struct4(int value)
{
Int1 = Int2 = Int3 = Int4 = value;
}
public int Int1;
public int Int2;
public int Int3;
public int Int4;
}
internal record struct Struct5
{
public Struct5(int value)
{
Int1 = Int2 = Int3 = Int4 = Int5 = value;
}
public int Int1;
public int Int2;
public int Int3;
public int Int4;
public int Int5;
}
internal record struct Struct6
{
public Struct6(int value)
{
Int1 = Int2 = Int3 = Int4 = Int5 = Int6 = value;
}
public int Int1;
public int Int2;
public int Int3;
public int Int4;
public int Int5;
public int Int6;
}
internal record struct Struct7
{
public Struct7(int value)
{
Int1 = Int2 = Int3 = Int4 = Int5 = Int6 = Int7 = value;
}
public int Int1;
public int Int2;
public int Int3;
public int Int4;
public int Int5;
public int Int6;
public int Int7;
}
internal record struct Struct8
{
public Struct8(int value)
{
Int1 = Int2 = Int3 = Int4 = Int5 = Int6 = Int7 = Int8 = value;
}
public int Int1;
public int Int2;
public int Int3;
public int Int4;
public int Int5;
public int Int6;
public int Int7;
public int Int8;
}
}
Loading…
Cancel
Save