Add benchmark for Or selector and avoid extra virtual calls getting list count.
This commit is contained in:
@@ -13,7 +13,7 @@ namespace Avalonia.Styling
|
||||
|
||||
public DescendantSelector(Selector? parent)
|
||||
{
|
||||
_parent = parent ?? throw new InvalidOperationException("Descendant selector must be preceeded by a selector.");
|
||||
_parent = parent ?? throw new InvalidOperationException("Descendant selector must be preceded by a selector.");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Avalonia.Styling
|
||||
/// <summary>
|
||||
/// The OR style selector.
|
||||
/// </summary>
|
||||
internal class OrSelector : Selector
|
||||
internal sealed class OrSelector : Selector
|
||||
{
|
||||
private readonly IReadOnlyList<Selector> _selectors;
|
||||
private string? _selectorString;
|
||||
@@ -42,18 +42,7 @@ namespace Avalonia.Styling
|
||||
public override bool IsCombinator => false;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Type? TargetType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_targetType == null)
|
||||
{
|
||||
_targetType = EvaluateTargetType();
|
||||
}
|
||||
|
||||
return _targetType;
|
||||
}
|
||||
}
|
||||
public override Type? TargetType => _targetType ??= EvaluateTargetType();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString(Style? owner)
|
||||
@@ -71,7 +60,9 @@ namespace Avalonia.Styling
|
||||
var activators = new OrActivatorBuilder();
|
||||
var neverThisInstance = false;
|
||||
|
||||
for (var i = 0; i < _selectors.Count; i++)
|
||||
var count = _selectors.Count;
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var match = _selectors[i].Match(control, parent, subscribe);
|
||||
|
||||
@@ -108,7 +99,9 @@ namespace Avalonia.Styling
|
||||
|
||||
internal override void ValidateNestingSelector(bool inControlTheme)
|
||||
{
|
||||
for (var i = 0; i < _selectors.Count; i++)
|
||||
var count = _selectors.Count;
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
_selectors[i].ValidateNestingSelector(inControlTheme);
|
||||
}
|
||||
@@ -118,7 +111,9 @@ namespace Avalonia.Styling
|
||||
{
|
||||
Type? result = null;
|
||||
|
||||
for (var i = 0; i < _selectors.Count; i++)
|
||||
var count = _selectors.Count;
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var selector = _selectors[i];
|
||||
if (selector.TargetType == null)
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Avalonia.Styling
|
||||
/// A selector that matches the common case of a type and/or name followed by a collection of
|
||||
/// style classes and pseudoclasses.
|
||||
/// </summary>
|
||||
internal class TypeNameAndClassSelector : Selector
|
||||
internal sealed class TypeNameAndClassSelector : Selector
|
||||
{
|
||||
private readonly Selector? _previous;
|
||||
private List<string>? _classes;
|
||||
@@ -85,12 +85,7 @@ namespace Avalonia.Styling
|
||||
/// <inheritdoc/>
|
||||
public override string ToString(Style? owner)
|
||||
{
|
||||
if (_selectorString == null)
|
||||
{
|
||||
_selectorString = BuildSelectorString(owner);
|
||||
}
|
||||
|
||||
return _selectorString;
|
||||
return _selectorString ??= BuildSelectorString(owner);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Avalonia.Benchmarks": {
|
||||
"commandName": "Project"
|
||||
},
|
||||
"Avalonia.Benchmarks (in-process)": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "--inprocess"
|
||||
},
|
||||
"Avalonia.Benchmarks (debug)": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "--debug"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Avalonia.Controls;
|
||||
using System;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Styling;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
@@ -11,6 +12,8 @@ namespace Avalonia.Benchmarks.Styling
|
||||
private readonly Calendar _matchingControl;
|
||||
private readonly Selector _isCalendarSelector;
|
||||
private readonly Selector _classSelector;
|
||||
private readonly Selector _orSelectorTwo;
|
||||
private readonly Selector _orSelectorFive;
|
||||
|
||||
public SelectorBenchmark()
|
||||
{
|
||||
@@ -23,6 +26,14 @@ namespace Avalonia.Benchmarks.Styling
|
||||
|
||||
_isCalendarSelector = Selectors.Is<Calendar>(null);
|
||||
_classSelector = Selectors.Class(null, className);
|
||||
|
||||
_orSelectorTwo = Selectors.Or(new AlwaysMatchSelector(), new AlwaysMatchSelector());
|
||||
_orSelectorFive = Selectors.Or(
|
||||
new AlwaysMatchSelector(),
|
||||
new AlwaysMatchSelector(),
|
||||
new AlwaysMatchSelector(),
|
||||
new AlwaysMatchSelector(),
|
||||
new AlwaysMatchSelector());
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
@@ -48,5 +59,40 @@ namespace Avalonia.Benchmarks.Styling
|
||||
{
|
||||
return _classSelector.Match(_matchingControl);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public SelectorMatch OrSelector_One_Match()
|
||||
{
|
||||
return _orSelectorTwo.Match(_matchingControl);
|
||||
}
|
||||
|
||||
[Benchmark]
|
||||
public SelectorMatch OrSelector_Five_Match()
|
||||
{
|
||||
return _orSelectorFive.Match(_matchingControl);
|
||||
}
|
||||
}
|
||||
|
||||
internal class AlwaysMatchSelector : Selector
|
||||
{
|
||||
public override bool InTemplate => false;
|
||||
|
||||
public override bool IsCombinator => false;
|
||||
|
||||
public override Type TargetType => null;
|
||||
|
||||
public override string ToString(Style owner)
|
||||
{
|
||||
return "Always";
|
||||
}
|
||||
|
||||
protected override SelectorMatch Evaluate(StyledElement control, IStyle parent, bool subscribe)
|
||||
{
|
||||
return SelectorMatch.AlwaysThisType;
|
||||
}
|
||||
|
||||
protected override Selector MovePrevious() => null;
|
||||
|
||||
protected override Selector MovePreviousOrParent() => null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user