Skip to content

Commit

Permalink
Improves performance of GetLayoutHandlerIndex (#18499)
Browse files Browse the repository at this point in the history
  • Loading branch information
albyrock87 committed Nov 6, 2023
1 parent 86b8757 commit 98924fa
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 2 deletions.
24 changes: 22 additions & 2 deletions src/Core/src/Handlers/Layout/LayoutExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,34 @@ internal static class LayoutExtensions

public static int GetLayoutHandlerIndex(this ILayout layout, IView view)
{
switch (layout.Count)
var count = layout.Count;
switch (count)
{
case 0:
return -1;
case 1:
return view == layout[0] ? 0 : -1;
default:
return layout.OrderByZIndex().IndexOf(view);
var found = false;
var zIndex = view.ZIndex;
var lowerViews = 0;

for (int i = 0; i < count; i++)
{
var child = layout[i];
var childZIndex = child.ZIndex;

if (child == view) {
found = true;
}

if (childZIndex < zIndex || !found && childZIndex == zIndex)
{
++lowerViews;
}
}

return found ? lowerViews : -1;
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/Core/src/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
[assembly: InternalsVisibleTo("Microsoft.Maui.Controls.DeviceTests")]
[assembly: InternalsVisibleTo("Microsoft.Maui.Controls.Core.UnitTests")]
[assembly: InternalsVisibleTo("Microsoft.Maui.Benchmarks.Droid")]
[assembly: InternalsVisibleTo("Core.Benchmarks")]
[assembly: InternalsVisibleTo("Comet")]
[assembly: InternalsVisibleTo("Comet.Tests")]
[assembly: InternalsVisibleTo("CommunityToolkit.Maui")]
Expand Down
31 changes: 31 additions & 0 deletions src/Core/tests/Benchmarks/Benchmarks/LayoutBenchmarker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using BenchmarkDotNet.Attributes;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;

namespace Microsoft.Maui.Benchmarks
{
[MemoryDiagnoser]
public class LayoutBenchmarker
{
static readonly Border[] Views = new[]
{
new Border(), new Border(), new Border(), new Border(), new Border(), new Border(), new Border(),
new Border(), new Border(), new Border(), new Border(), new Border(), new Border(), new Border()
};

static readonly int Iterations = Views.Length;

[Benchmark]
public void GetLayoutHandlerIndex()
{
var layout = new VerticalStackLayout();

for (int i = 0; i < Iterations; i++)
{
var view = Views[i];
layout.Add(view);
layout.GetLayoutHandlerIndex(view);
}
}
}
}
35 changes: 35 additions & 0 deletions src/Core/tests/UnitTests/Layouts/ZIndexTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,41 @@ public void LayoutHandlerIndexFollowsAddOrderWhenZIndexesAreEqual()
Assert.Equal(2, layout.GetLayoutHandlerIndex(view2));
Assert.Equal(3, layout.GetLayoutHandlerIndex(view3));
}

[Fact]
public void LayoutHandlerIndexIsNegativeWhenChildIsNotFound()
{
var layout = new FakeLayout();
var view0 = CreateTestView(zIndex: 0);

Assert.Equal(-1, layout.GetLayoutHandlerIndex(view0));

layout.Add(CreateTestView(zIndex: 0));
Assert.Equal(-1, layout.GetLayoutHandlerIndex(view0));


layout.Add(CreateTestView(zIndex: 0));
Assert.Equal(-1, layout.GetLayoutHandlerIndex(view0));
}

[Fact]
public void LayoutHandlerIndexPreservesAddOrderForEqualZIndexes()
{
var layout = new FakeLayout();
var view0 = CreateTestView(zIndex: 10);
var view1 = CreateTestView(zIndex: 10);
var view2 = CreateTestView(zIndex: 10);
var view3 = CreateTestView(zIndex: 5);
layout.Add(view0);
layout.Add(view1);
layout.Add(view2);
layout.Add(view3);

Assert.Equal(1, layout.GetLayoutHandlerIndex(view0));
Assert.Equal(2, layout.GetLayoutHandlerIndex(view1));
Assert.Equal(3, layout.GetLayoutHandlerIndex(view2));
Assert.Equal(0, layout.GetLayoutHandlerIndex(view3));
}

[Fact]
public void ItemsOrderByZIndex()
Expand Down

0 comments on commit 98924fa

Please sign in to comment.