Browse Source

Merge pull request #5049 from MarchingCube/opt-children-notifications

Optimize logical/visual children iteration on the hot path
pull/5056/head
Dariusz Komosiński 6 years ago
committed by GitHub
parent
commit
84cc496c45
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      src/Avalonia.Controls/Primitives/TemplatedControl.cs
  2. 48
      src/Avalonia.Styling/StyledElement.cs
  3. 37
      src/Avalonia.Visuals/Visual.cs
  4. 2
      tests/Avalonia.Benchmarks/NullRenderingPlatform.cs

9
src/Avalonia.Controls/Primitives/TemplatedControl.cs

@ -354,11 +354,14 @@ namespace Avalonia.Controls.Primitives
{
control.SetValue(TemplatedParentProperty, this);
foreach (var child in control.LogicalChildren)
var children = control.LogicalChildren;
var count = children.Count;
for (var i = 0; i < count; i++)
{
if (child is IControl c)
if (children[i] is IControl child)
{
ApplyTemplatedParent(c);
ApplyTemplatedParent(child);
}
}
}

48
src/Avalonia.Styling/StyledElement.cs

@ -1,8 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using Avalonia.Animation;
using Avalonia.Collections;
using Avalonia.Controls;
@ -479,16 +479,16 @@ namespace Avalonia
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
SetLogicalParent(e.NewItems.Cast<ILogical>());
SetLogicalParent(e.NewItems);
break;
case NotifyCollectionChangedAction.Remove:
ClearLogicalParent(e.OldItems.Cast<ILogical>());
ClearLogicalParent(e.OldItems);
break;
case NotifyCollectionChangedAction.Replace:
ClearLogicalParent(e.OldItems.Cast<ILogical>());
SetLogicalParent(e.NewItems.Cast<ILogical>());
ClearLogicalParent(e.OldItems);
SetLogicalParent(e.NewItems);
break;
case NotifyCollectionChangedAction.Reset:
@ -702,13 +702,32 @@ namespace Avalonia
OnDataContextChanged(EventArgs.Empty);
}
private void SetLogicalParent(IEnumerable<ILogical> children)
private void SetLogicalParent(IList children)
{
foreach (var i in children)
var count = children.Count;
for (var i = 0; i < count; i++)
{
var logical = (ILogical) children[i];
if (logical.LogicalParent is null)
{
((ISetLogicalParent)logical).SetParent(this);
}
}
}
private void ClearLogicalParent(IList children)
{
var count = children.Count;
for (var i = 0; i < count; i++)
{
if (i.LogicalParent == null)
var logical = (ILogical) children[i];
if (logical.LogicalParent == this)
{
((ISetLogicalParent)i).SetParent(this);
((ISetLogicalParent)logical).SetParent(null);
}
}
}
@ -784,17 +803,6 @@ namespace Avalonia
}
}
private void ClearLogicalParent(IEnumerable<ILogical> children)
{
foreach (var i in children)
{
if (i.LogicalParent == this)
{
((ISetLogicalParent)i).SetParent(null);
}
}
}
private void NotifyResourcesChanged(
ResourcesChangedEventArgs? e = null,
bool propagate = true)

37
src/Avalonia.Visuals/Visual.cs

@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using Avalonia.Collections;
using Avalonia.Data;
@ -619,34 +620,30 @@ namespace Avalonia
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (Visual v in e.NewItems)
{
v.SetVisualParent(this);
}
SetVisualParent(e.NewItems, this);
break;
case NotifyCollectionChangedAction.Remove:
foreach (Visual v in e.OldItems)
{
v.SetVisualParent(null);
}
SetVisualParent(e.OldItems, null);
break;
case NotifyCollectionChangedAction.Replace:
foreach (Visual v in e.OldItems)
{
v.SetVisualParent(null);
}
foreach (Visual v in e.NewItems)
{
v.SetVisualParent(this);
}
SetVisualParent(e.OldItems, null);
SetVisualParent(e.NewItems, this);
break;
}
}
private static void SetVisualParent(IList children, Visual parent)
{
var count = children.Count;
for (var i = 0; i < count; i++)
{
var visual = (Visual) children[i];
visual.SetVisualParent(parent);
}
}
}
}

2
tests/Avalonia.Benchmarks/NullRenderingPlatform.cs

@ -28,7 +28,7 @@ namespace Avalonia.Benchmarks
public IGeometryImpl CreateRectangleGeometry(Rect rect)
{
throw new NotImplementedException();
return new MockStreamGeometryImpl();
}
public IStreamGeometryImpl CreateStreamGeometry()

Loading…
Cancel
Save