committed by
GitHub
46 changed files with 2841 additions and 341 deletions
@ -1,28 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8" ?> |
|
||||
<!-- |
|
||||
This file specifies which parts of the BCL or Blazor packages must not be |
|
||||
stripped by the IL Linker even if they aren't referenced by user code. |
|
||||
--> |
|
||||
<linker> |
|
||||
<assembly fullname="mscorlib"> |
|
||||
<!-- |
|
||||
Preserve the methods in WasmRuntime because its methods are called by |
|
||||
JavaScript client-side code to implement timers. |
|
||||
Fixes: https://github.com/dotnet/blazor/issues/239 |
|
||||
--> |
|
||||
<type fullname="System.Threading.WasmRuntime"/> |
|
||||
</assembly> |
|
||||
|
|
||||
<assembly fullname="System.Core"> |
|
||||
<!-- |
|
||||
System.Linq.Expressions* is required by Json.NET and any |
|
||||
expression.Compile caller. The assembly isn't stripped. |
|
||||
--> |
|
||||
<type fullname="System.Linq.Expressions*"/> |
|
||||
</assembly> |
|
||||
<!-- |
|
||||
In this example, the app's entry point assembly is listed. The assembly |
|
||||
isn't stripped by the IL Linker. |
|
||||
--> |
|
||||
<assembly fullname="ControlCatalog" preserve="All" /> |
|
||||
</linker> |
|
||||
@ -0,0 +1,476 @@ |
|||||
|
// Color conversion portions of this source file are adapted from the Windows Community Toolkit project.
|
||||
|
// (https://github.com/CommunityToolkit/WindowsCommunityToolkit)
|
||||
|
//
|
||||
|
// Licensed to The Avalonia Project under MIT License, courtesy of The .NET Foundation.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Globalization; |
||||
|
using System.Text; |
||||
|
using Avalonia.Utilities; |
||||
|
|
||||
|
namespace Avalonia.Media |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Defines a color using the hue/saturation/lightness (HSL) model.
|
||||
|
/// </summary>
|
||||
|
#if !BUILDTASK
|
||||
|
public |
||||
|
#endif
|
||||
|
readonly struct HslColor : IEquatable<HslColor> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="HslColor"/> struct.
|
||||
|
/// </summary>
|
||||
|
/// <param name="alpha">The Alpha (transparency) component in the range from 0..1.</param>
|
||||
|
/// <param name="hue">The Hue component in the range from 0..360.
|
||||
|
/// Note that 360 is equivalent to 0 and will be adjusted automatically.</param>
|
||||
|
/// <param name="saturation">The Saturation component in the range from 0..1.</param>
|
||||
|
/// <param name="lightness">The Lightness component in the range from 0..1.</param>
|
||||
|
public HslColor( |
||||
|
double alpha, |
||||
|
double hue, |
||||
|
double saturation, |
||||
|
double lightness) |
||||
|
{ |
||||
|
A = MathUtilities.Clamp(alpha, 0.0, 1.0); |
||||
|
H = MathUtilities.Clamp(hue, 0.0, 360.0); |
||||
|
S = MathUtilities.Clamp(saturation, 0.0, 1.0); |
||||
|
L = MathUtilities.Clamp(lightness, 0.0, 1.0); |
||||
|
|
||||
|
// The maximum value of Hue is technically 360 minus epsilon (just below 360).
|
||||
|
// This is because, in a color circle, 360 degrees is equivalent to 0 degrees.
|
||||
|
// However, that is too tricky to work with in code and isn't as intuitive.
|
||||
|
// Therefore, since 360 == 0, just wrap 360 if needed back to 0.
|
||||
|
H = (H == 360.0 ? 0 : H); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="HslColor"/> struct.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// This constructor exists only for internal use where performance is critical.
|
||||
|
/// Whether or not the component values are in the correct ranges must be known.
|
||||
|
/// </remarks>
|
||||
|
/// <param name="alpha">The Alpha (transparency) component in the range from 0..1.</param>
|
||||
|
/// <param name="hue">The Hue component in the range from 0..360.
|
||||
|
/// Note that 360 is equivalent to 0 and will be adjusted automatically.</param>
|
||||
|
/// <param name="saturation">The Saturation component in the range from 0..1.</param>
|
||||
|
/// <param name="lightness">The Lightness component in the range from 0..1.</param>
|
||||
|
/// <param name="clampValues">Whether to clamp component values to their required ranges.</param>
|
||||
|
internal HslColor( |
||||
|
double alpha, |
||||
|
double hue, |
||||
|
double saturation, |
||||
|
double lightness, |
||||
|
bool clampValues) |
||||
|
{ |
||||
|
if (clampValues) |
||||
|
{ |
||||
|
A = MathUtilities.Clamp(alpha, 0.0, 1.0); |
||||
|
H = MathUtilities.Clamp(hue, 0.0, 360.0); |
||||
|
S = MathUtilities.Clamp(saturation, 0.0, 1.0); |
||||
|
L = MathUtilities.Clamp(lightness, 0.0, 1.0); |
||||
|
|
||||
|
// See comments in constructor above
|
||||
|
H = (H == 360.0 ? 0 : H); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
A = alpha; |
||||
|
H = hue; |
||||
|
S = saturation; |
||||
|
L = lightness; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="HslColor"/> struct.
|
||||
|
/// </summary>
|
||||
|
/// <param name="color">The RGB color to convert to HSL.</param>
|
||||
|
public HslColor(Color color) |
||||
|
{ |
||||
|
var hsl = Color.ToHsl(color); |
||||
|
|
||||
|
A = hsl.A; |
||||
|
H = hsl.H; |
||||
|
S = hsl.S; |
||||
|
L = hsl.L; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the Alpha (transparency) component in the range from 0..1.
|
||||
|
/// </summary>
|
||||
|
public double A { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the Hue component in the range from 0..360.
|
||||
|
/// Note that 360 is equivalent to 0 and will be adjusted automatically.
|
||||
|
/// </summary>
|
||||
|
public double H { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the Saturation component in the range from 0..1.
|
||||
|
/// </summary>
|
||||
|
public double S { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the Lightness component in the range from 0..1.
|
||||
|
/// </summary>
|
||||
|
public double L { get; } |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public bool Equals(HslColor other) |
||||
|
{ |
||||
|
return other.A == A && |
||||
|
other.H == H && |
||||
|
other.S == S && |
||||
|
other.L == L; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override bool Equals(object? obj) |
||||
|
{ |
||||
|
if (obj is HslColor hslColor) |
||||
|
{ |
||||
|
return Equals(hslColor); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a hashcode for this object.
|
||||
|
/// Hashcode is not guaranteed to be unique.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The hashcode for this object.</returns>
|
||||
|
public override int GetHashCode() |
||||
|
{ |
||||
|
// Same algorithm as Color
|
||||
|
// This is used instead of HashCode.Combine() due to .NET Standard 2.0 requirements
|
||||
|
unchecked |
||||
|
{ |
||||
|
int hashCode = A.GetHashCode(); |
||||
|
hashCode = (hashCode * 397) ^ H.GetHashCode(); |
||||
|
hashCode = (hashCode * 397) ^ S.GetHashCode(); |
||||
|
hashCode = (hashCode * 397) ^ L.GetHashCode(); |
||||
|
return hashCode; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the RGB color model equivalent of this HSL color.
|
||||
|
/// </summary>
|
||||
|
/// <returns>The RGB equivalent color.</returns>
|
||||
|
public Color ToRgb() |
||||
|
{ |
||||
|
// Use the by-component conversion method directly for performance
|
||||
|
return HslColor.ToRgb(H, S, L, A); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override string ToString() |
||||
|
{ |
||||
|
var sb = new StringBuilder(); |
||||
|
|
||||
|
// Use a format similar to CSS. However:
|
||||
|
// - To ensure precision is never lost, allow decimal places.
|
||||
|
// This is especially important for round-trip serialization.
|
||||
|
// - To maintain numerical consistency, do not use percent.
|
||||
|
//
|
||||
|
// Example:
|
||||
|
//
|
||||
|
// hsla(hue, saturation, lightness, alpha)
|
||||
|
// hsla(230, 1.0, 0.5, 1.0)
|
||||
|
//
|
||||
|
|
||||
|
sb.Append("hsva("); |
||||
|
sb.Append(H.ToString(CultureInfo.InvariantCulture)); |
||||
|
sb.Append(", "); |
||||
|
sb.Append(S.ToString(CultureInfo.InvariantCulture)); |
||||
|
sb.Append(", "); |
||||
|
sb.Append(L.ToString(CultureInfo.InvariantCulture)); |
||||
|
sb.Append(", "); |
||||
|
sb.Append(A.ToString(CultureInfo.InvariantCulture)); |
||||
|
sb.Append(')'); |
||||
|
|
||||
|
return sb.ToString(); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Parses an HSL color string.
|
||||
|
/// </summary>
|
||||
|
/// <param name="s">The HSL color string to parse.</param>
|
||||
|
/// <returns>The parsed <see cref="HslColor"/>.</returns>
|
||||
|
public static HslColor Parse(string s) |
||||
|
{ |
||||
|
if (s is null) |
||||
|
{ |
||||
|
throw new ArgumentNullException(nameof(s)); |
||||
|
} |
||||
|
|
||||
|
if (TryParse(s, out HslColor hslColor)) |
||||
|
{ |
||||
|
return hslColor; |
||||
|
} |
||||
|
|
||||
|
throw new FormatException($"Invalid HSL color string: '{s}'."); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Parses an HSL color string.
|
||||
|
/// </summary>
|
||||
|
/// <param name="s">The HSL color string to parse.</param>
|
||||
|
/// <param name="hslColor">The parsed <see cref="HslColor"/>.</param>
|
||||
|
/// <returns>True if parsing was successful; otherwise, false.</returns>
|
||||
|
public static bool TryParse(string s, out HslColor hslColor) |
||||
|
{ |
||||
|
hslColor = default; |
||||
|
|
||||
|
if (s is null) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
string workingString = s.Trim(); |
||||
|
|
||||
|
if (workingString.Length == 0 || |
||||
|
workingString.IndexOf(",", StringComparison.Ordinal) < 0) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (workingString.Length > 6 && |
||||
|
workingString.StartsWith("hsla(", StringComparison.OrdinalIgnoreCase) && |
||||
|
workingString.EndsWith(")", StringComparison.Ordinal)) |
||||
|
{ |
||||
|
workingString = workingString.Substring(5, workingString.Length - 6); |
||||
|
} |
||||
|
|
||||
|
if (workingString.Length > 5 && |
||||
|
workingString.StartsWith("hsl(", StringComparison.OrdinalIgnoreCase) && |
||||
|
workingString.EndsWith(")", StringComparison.Ordinal)) |
||||
|
{ |
||||
|
workingString = workingString.Substring(4, workingString.Length - 5); |
||||
|
} |
||||
|
|
||||
|
string[] components = workingString.Split(','); |
||||
|
|
||||
|
if (components.Length == 3) // HSL
|
||||
|
{ |
||||
|
if (double.TryParse(components[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) && |
||||
|
TryInternalParse(components[1], out double saturation) && |
||||
|
TryInternalParse(components[2], out double lightness)) |
||||
|
{ |
||||
|
hslColor = new HslColor(1.0, hue, saturation, lightness); |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
else if (components.Length == 4) // HSLA
|
||||
|
{ |
||||
|
if (double.TryParse(components[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) && |
||||
|
TryInternalParse(components[1], out double saturation) && |
||||
|
TryInternalParse(components[2], out double lightness) && |
||||
|
TryInternalParse(components[3], out double alpha)) |
||||
|
{ |
||||
|
hslColor = new HslColor(alpha, hue, saturation, lightness); |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Local function to specially parse a double value with an optional percentage sign
|
||||
|
bool TryInternalParse(string inString, out double outDouble) |
||||
|
{ |
||||
|
// The percent sign, if it exists, must be at the end of the number
|
||||
|
int percentIndex = inString.IndexOf("%", StringComparison.Ordinal); |
||||
|
|
||||
|
if (percentIndex >= 0) |
||||
|
{ |
||||
|
var result = double.TryParse( |
||||
|
inString.Substring(0, percentIndex), |
||||
|
NumberStyles.Number, |
||||
|
CultureInfo.InvariantCulture, |
||||
|
out double percentage); |
||||
|
|
||||
|
outDouble = percentage / 100.0; |
||||
|
return result; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return double.TryParse( |
||||
|
inString, |
||||
|
NumberStyles.Number, |
||||
|
CultureInfo.InvariantCulture, |
||||
|
out outDouble); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new <see cref="HslColor"/> from individual color component values.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// This exists for symmetry with the <see cref="Color"/> struct; however, the
|
||||
|
/// appropriate constructor should commonly be used instead.
|
||||
|
/// </remarks>
|
||||
|
/// <param name="a">The Alpha (transparency) component in the range from 0..1.</param>
|
||||
|
/// <param name="h">The Hue component in the range from 0..360.</param>
|
||||
|
/// <param name="s">The Saturation component in the range from 0..1.</param>
|
||||
|
/// <param name="l">The Lightness component in the range from 0..1.</param>
|
||||
|
/// <returns>A new <see cref="HslColor"/> built from the individual color component values.</returns>
|
||||
|
public static HslColor FromAhsl(double a, double h, double s, double l) |
||||
|
{ |
||||
|
return new HslColor(a, h, s, l); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Creates a new <see cref="HslColor"/> from individual color component values.
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// This exists for symmetry with the <see cref="Color"/> struct; however, the
|
||||
|
/// appropriate constructor should commonly be used instead.
|
||||
|
/// </remarks>
|
||||
|
/// <param name="h">The Hue component in the range from 0..360.</param>
|
||||
|
/// <param name="s">The Saturation component in the range from 0..1.</param>
|
||||
|
/// <param name="l">The Lightness component in the range from 0..1.</param>
|
||||
|
/// <returns>A new <see cref="HslColor"/> built from the individual color component values.</returns>
|
||||
|
public static HslColor FromHsl(double h, double s, double l) |
||||
|
{ |
||||
|
return new HslColor(1.0, h, s, l); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the given HSL color to its RGB color equivalent.
|
||||
|
/// </summary>
|
||||
|
/// <param name="hslColor">The color in the HSL color model.</param>
|
||||
|
/// <returns>A new RGB <see cref="Color"/> equivalent to the given HSLA values.</returns>
|
||||
|
public static Color ToRgb(HslColor hslColor) |
||||
|
{ |
||||
|
return HslColor.ToRgb(hslColor.H, hslColor.S, hslColor.L, hslColor.A); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Converts the given HSLA color component values to their RGB color equivalent.
|
||||
|
/// </summary>
|
||||
|
/// <param name="hue">The Hue component in the HSL color model in the range from 0..360.</param>
|
||||
|
/// <param name="saturation">The Saturation component in the HSL color model in the range from 0..1.</param>
|
||||
|
/// <param name="lightness">The Lightness component in the HSL color model in the range from 0..1.</param>
|
||||
|
/// <param name="alpha">The Alpha component in the range from 0..1.</param>
|
||||
|
/// <returns>A new RGB <see cref="Color"/> equivalent to the given HSLA values.</returns>
|
||||
|
public static Color ToRgb( |
||||
|
double hue, |
||||
|
double saturation, |
||||
|
double lightness, |
||||
|
double alpha = 1.0) |
||||
|
{ |
||||
|
// Note: Conversion code is originally based on ColorHelper in the Windows Community Toolkit (licensed MIT)
|
||||
|
// https://github.com/CommunityToolkit/WindowsCommunityToolkit/blob/main/Microsoft.Toolkit.Uwp/Helpers/ColorHelper.cs
|
||||
|
// It has been modified to ensure input ranges and not throw exceptions.
|
||||
|
|
||||
|
// We want the hue to be between 0 and 359,
|
||||
|
// so we first ensure that that's the case.
|
||||
|
while (hue >= 360.0) |
||||
|
{ |
||||
|
hue -= 360.0; |
||||
|
} |
||||
|
|
||||
|
while (hue < 0.0) |
||||
|
{ |
||||
|
hue += 360.0; |
||||
|
} |
||||
|
|
||||
|
// We similarly clamp saturation, lightness and alpha between 0 and 1.
|
||||
|
saturation = saturation < 0.0 ? 0.0 : saturation; |
||||
|
saturation = saturation > 1.0 ? 1.0 : saturation; |
||||
|
|
||||
|
lightness = lightness < 0.0 ? 0.0 : lightness; |
||||
|
lightness = lightness > 1.0 ? 1.0 : lightness; |
||||
|
|
||||
|
alpha = alpha < 0.0 ? 0.0 : alpha; |
||||
|
alpha = alpha > 1.0 ? 1.0 : alpha; |
||||
|
|
||||
|
double chroma = (1 - Math.Abs((2 * lightness) - 1)) * saturation; |
||||
|
double h1 = hue / 60; |
||||
|
double x = chroma * (1 - Math.Abs((h1 % 2) - 1)); |
||||
|
double m = lightness - (0.5 * chroma); |
||||
|
double r1, g1, b1; |
||||
|
|
||||
|
if (h1 < 1) |
||||
|
{ |
||||
|
r1 = chroma; |
||||
|
g1 = x; |
||||
|
b1 = 0; |
||||
|
} |
||||
|
else if (h1 < 2) |
||||
|
{ |
||||
|
r1 = x; |
||||
|
g1 = chroma; |
||||
|
b1 = 0; |
||||
|
} |
||||
|
else if (h1 < 3) |
||||
|
{ |
||||
|
r1 = 0; |
||||
|
g1 = chroma; |
||||
|
b1 = x; |
||||
|
} |
||||
|
else if (h1 < 4) |
||||
|
{ |
||||
|
r1 = 0; |
||||
|
g1 = x; |
||||
|
b1 = chroma; |
||||
|
} |
||||
|
else if (h1 < 5) |
||||
|
{ |
||||
|
r1 = x; |
||||
|
g1 = 0; |
||||
|
b1 = chroma; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
r1 = chroma; |
||||
|
g1 = 0; |
||||
|
b1 = x; |
||||
|
} |
||||
|
|
||||
|
return Color.FromArgb( |
||||
|
(byte)Math.Round(255 * alpha), |
||||
|
(byte)Math.Round(255 * (r1 + m)), |
||||
|
(byte)Math.Round(255 * (g1 + m)), |
||||
|
(byte)Math.Round(255 * (b1 + m))); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Indicates whether the values of two specified <see cref="HslColor"/> objects are equal.
|
||||
|
/// </summary>
|
||||
|
/// <param name="left">The first object to compare.</param>
|
||||
|
/// <param name="right">The second object to compare.</param>
|
||||
|
/// <returns>True if left and right are equal; otherwise, false.</returns>
|
||||
|
public static bool operator ==(HslColor left, HslColor right) |
||||
|
{ |
||||
|
return left.Equals(right); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Indicates whether the values of two specified <see cref="HslColor"/> objects are not equal.
|
||||
|
/// </summary>
|
||||
|
/// <param name="left">The first object to compare.</param>
|
||||
|
/// <param name="right">The second object to compare.</param>
|
||||
|
/// <returns>True if left and right are not equal; otherwise, false.</returns>
|
||||
|
public static bool operator !=(HslColor left, HslColor right) |
||||
|
{ |
||||
|
return !(left == right); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Explicit conversion from an <see cref="HslColor"/> to a <see cref="Color"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="hslColor">The <see cref="HslColor"/> to convert.</param>
|
||||
|
public static explicit operator Color(HslColor hslColor) |
||||
|
{ |
||||
|
return hslColor.ToRgb(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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 |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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…
Reference in new issue