Browse Source

Reuse empty value store arrays.

pull/5074/head
Dariusz Komosinski 6 years ago
parent
commit
dc698b3b1d
  1. 24
      src/Avalonia.Base/Utilities/AvaloniaPropertyValueStore.cs
  2. 3
      tests/Avalonia.Benchmarks/Layout/ControlsBenchmark.cs
  3. 14
      tests/Avalonia.Benchmarks/NullCursorFactory.cs

24
src/Avalonia.Base/Utilities/AvaloniaPropertyValueStore.cs

@ -1,5 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
#nullable enable
namespace Avalonia.Utilities namespace Avalonia.Utilities
{ {
@ -9,12 +12,14 @@ namespace Avalonia.Utilities
/// <typeparam name="TValue">Stored value type.</typeparam> /// <typeparam name="TValue">Stored value type.</typeparam>
internal sealed class AvaloniaPropertyValueStore<TValue> internal sealed class AvaloniaPropertyValueStore<TValue>
{ {
// The last item in the list is always int.MaxValue.
private static readonly Entry[] s_emptyEntries = { new Entry { PropertyId = int.MaxValue, Value = default! } };
private Entry[] _entries; private Entry[] _entries;
public AvaloniaPropertyValueStore() public AvaloniaPropertyValueStore()
{ {
// The last item in the list is always int.MaxValue _entries = s_emptyEntries;
_entries = new[] { new Entry { PropertyId = int.MaxValue, Value = default } };
} }
private (int, bool) TryFindEntry(int propertyId) private (int, bool) TryFindEntry(int propertyId)
@ -86,7 +91,7 @@ namespace Avalonia.Utilities
return (0, false); return (0, false);
} }
public bool TryGetValue(AvaloniaProperty property, out TValue value) public bool TryGetValue(AvaloniaProperty property, [MaybeNull] out TValue value)
{ {
(int index, bool found) = TryFindEntry(property.Id); (int index, bool found) = TryFindEntry(property.Id);
if (!found) if (!found)
@ -132,7 +137,18 @@ namespace Avalonia.Utilities
if (found) if (found)
{ {
Entry[] entries = new Entry[_entries.Length - 1]; var newLength = _entries.Length - 1;
// Special case - one element left means that value store is empty so we can just reuse our "empty" array.
if (newLength == 1)
{
_entries = s_emptyEntries;
return;
}
var entries = new Entry[newLength];
int ix = 0; int ix = 0;
for (int i = 0; i < _entries.Length; ++i) for (int i = 0; i < _entries.Length; ++i)

3
tests/Avalonia.Benchmarks/Layout/ControlsBenchmark.cs

@ -17,7 +17,8 @@ namespace Avalonia.Benchmarks.Layout
_app = UnitTestApplication.Start( _app = UnitTestApplication.Start(
TestServices.StyledWindow.With( TestServices.StyledWindow.With(
renderInterface: new NullRenderingPlatform(), renderInterface: new NullRenderingPlatform(),
threadingInterface: new NullThreadingPlatform())); threadingInterface: new NullThreadingPlatform(),
standardCursorFactory: new NullCursorFactory()));
_root = new TestRoot(true, null) _root = new TestRoot(true, null)
{ {

14
tests/Avalonia.Benchmarks/NullCursorFactory.cs

@ -0,0 +1,14 @@
using System;
using Avalonia.Input;
using Avalonia.Platform;
namespace Avalonia.Benchmarks
{
internal class NullCursorFactory : IStandardCursorFactory
{
public IPlatformHandle GetCursor(StandardCursorType cursorType)
{
return new PlatformHandle(IntPtr.Zero, "null");
}
}
}
Loading…
Cancel
Save