Skip to content

Commit

Permalink
perf(dp): Reduce property search allocations
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromelaban committed Feb 23, 2023
1 parent 82fc8e7 commit b3af05a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 8 deletions.
18 changes: 13 additions & 5 deletions src/Uno.UI/UI/Xaml/DependencyProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ public sealed partial class DependencyProperty
private readonly static TypeToPropertiesDictionary _getPropertiesForType = new TypeToPropertiesDictionary();
private readonly static NameToPropertyDictionary _getPropertyCache = new NameToPropertyDictionary();

/// <summary>
/// A static <see cref="PropertyCacheEntry"/> used for lookups and avoid creating new instances. This assumes that uses are non-reentrant.
/// </summary>
private readonly static PropertyCacheEntry _searchPropertyCacheEntry = new(typeof(object), "");


private readonly static FrameworkPropertiesForTypeDictionary _getFrameworkPropertiesForType = new FrameworkPropertiesForTypeDictionary();

private readonly PropertyMetadata _ownerTypeMetadata; // For perf consideration, we keep direct ref the metadata for the owner type
Expand Down Expand Up @@ -317,12 +323,12 @@ internal bool IsUnoType
/// <returns>A <see cref="DependencyProperty"/> instance, otherwise null it not found.</returns>
internal static DependencyProperty GetProperty(Type type, string name)
{
DependencyProperty result = null;
var key = new PropertyCacheEntry(type, name);
DependencyProperty result;
_searchPropertyCacheEntry.Update(type, name);

if (!_getPropertyCache.TryGetValue(key, out result))
if (!_getPropertyCache.TryGetValue(_searchPropertyCacheEntry, out result))
{
_getPropertyCache.Add(key, result = InternalGetProperty(type, name));
_getPropertyCache.Add(_searchPropertyCacheEntry.Clone(), result = InternalGetProperty(type, name));
}

return result;
Expand All @@ -332,7 +338,9 @@ private static void ResetGetPropertyCache(Type ownerType, string name)
{
if (_getPropertyCache.Count != 0)
{
_getPropertyCache.Remove(new PropertyCacheEntry(ownerType, name));
_searchPropertyCacheEntry.Update(ownerType, name);

_getPropertyCache.Remove(_searchPropertyCacheEntry);
}
}

Expand Down
26 changes: 23 additions & 3 deletions src/Uno.UI/UI/Xaml/DependencyPropertyCacheEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Uno.Core.Comparison;

Expand All @@ -12,11 +13,30 @@ namespace Windows.UI.Xaml
/// </summary>
internal class PropertyCacheEntry
{
private readonly Type Type;
private readonly string Name;
private readonly int CachedHashCode;
private Type Type;
private string Name;
private int CachedHashCode;

public PropertyCacheEntry(Type type, string name)
{
Update(type, name);
}

private PropertyCacheEntry(PropertyCacheEntry other)
{
CachedHashCode = other.CachedHashCode;
Name = other.Name;
Type = other.Type;
}

public PropertyCacheEntry Clone()
=> new(this);

/// <summary>
/// Mutates the fields from this instance
/// </summary>
[MemberNotNull(nameof(Type), nameof(Name))]
public void Update(Type type, string name)
{
this.Type = type;
this.Name = name;
Expand Down

0 comments on commit b3af05a

Please sign in to comment.