Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(dp): Reduce property search allocations #11445

Merged
merged 1 commit into from
Feb 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 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();


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,11 @@ 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);
_searchPropertyCacheEntry.Update(type, name);

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

return result;
Expand All @@ -332,7 +337,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: 22 additions & 4 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,28 @@ 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)
public PropertyCacheEntry()
=> Update(typeof(object), "");

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