Skip to content

Commit

Permalink
perf: Refactor inherited DPs retrieval for less memory during app sta…
Browse files Browse the repository at this point in the history
…rtup
  • Loading branch information
Youssef1313 committed Aug 31, 2024
1 parent 8122799 commit 69f9ef4
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 107 deletions.
2 changes: 1 addition & 1 deletion src/Uno.UI/UI/Xaml/DependencyObjectStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1631,7 +1631,7 @@ private void PropagateInheritedProperties(DependencyObjectStore? childStore = nu
}

// Raise the property change for the current values
var props = DependencyProperty.GetFrameworkPropertiesForType(_originalObjectType, FrameworkPropertyMetadataOptions.Inherits);
var props = DependencyProperty.GetInheritedPropertiesForType(_originalObjectType);

// Not using the ActualInstance property here because we need to get a WeakReference instead.
var instanceRef = _originalObjectRef != null ? _originalObjectRef : ThisWeakReference;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
#nullable enable

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using Microsoft.UI.Xaml;
using Uno.Extensions;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Uno;
using System.Threading;
using Uno.Collections;

using _Key = Uno.CachedTuple<System.Type, Microsoft.UI.Xaml.FrameworkPropertyMetadataOptions>;
using System.Collections;
using Uno.Extensions;

namespace Microsoft.UI.Xaml
{
Expand All @@ -25,7 +23,7 @@ private class FrameworkPropertiesForTypeDictionary
// So we don't use pooling to not cause pool exhaustion by renting without returning.
private readonly HashtableEx _entries = new HashtableEx(usePooling: false);

internal bool TryGetValue(_Key key, out DependencyProperty[]? result)
internal bool TryGetValue(Type key, out DependencyProperty[]? result)
{
if (_entries.TryGetValue(key, out var value))
{
Expand All @@ -38,7 +36,7 @@ internal bool TryGetValue(_Key key, out DependencyProperty[]? result)
return false;
}

internal void Add(_Key key, DependencyProperty[] value)
internal void Add(Type key, DependencyProperty[] value)
=> _entries.Add(key, value);

internal void Clear() => _entries.Clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,17 @@ internal void Add(Type type, string name, DependencyProperty property)
typeTable!.Add(name, property);
}

internal void AppendPropertiesForType(Type type, List<DependencyProperty> properties)
internal void AppendInheritedPropertiesForType(Type type, List<DependencyProperty> properties)
{
if (TryGetTypeTable(type, out var typeTable))
{
foreach (var value in typeTable!.Values)
{
properties.Add((DependencyProperty)value);
var dp = (DependencyProperty)value;
if (dp.IsInherited)
{
properties.Add(dp);
}
}
}
}
Expand Down

This file was deleted.

77 changes: 20 additions & 57 deletions src/Uno.UI/UI/Xaml/DependencyProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ public sealed partial class DependencyProperty
{
private readonly static DependencyPropertyRegistry _registry = new DependencyPropertyRegistry();

private readonly static TypeToPropertiesDictionary _getPropertiesForType = new TypeToPropertiesDictionary();
private readonly static NameToPropertyDictionary _getPropertyCache = new NameToPropertyDictionary();
private static object DefaultThemeAnimationDurationBox = new Duration(FeatureConfiguration.ThemeAnimation.DefaultThemeAnimationDuration);

Expand All @@ -48,7 +47,7 @@ public sealed partial class DependencyProperty
private readonly static PropertyCacheEntry _searchPropertyCacheEntry = new();


private readonly static FrameworkPropertiesForTypeDictionary _getFrameworkPropertiesForType = new FrameworkPropertiesForTypeDictionary();
private readonly static FrameworkPropertiesForTypeDictionary _getInheritedPropertiesForType = new FrameworkPropertiesForTypeDictionary();

private readonly PropertyMetadata _ownerTypeMetadata; // For perf consideration, we keep direct ref the metadata for the owner type

Expand Down Expand Up @@ -380,37 +379,19 @@ private static DependencyProperty InternalGetProperty(Type type, string name)
return null;
}

/// <summary>
/// Gets the dependencies properties for the specified type
/// </summary>
/// <param name="type">A dependency object</param>
/// <returns>An array of Dependency Properties.</returns>
internal static DependencyProperty[] GetPropertiesForType(Type type)
{
DependencyProperty[] result = null;

if (!_getPropertiesForType.TryGetValue(type, out result))
{
_getPropertiesForType.Add(type, result = InternalGetPropertiesForType(type));
}

return result;
}

/// <summary>
/// Gets the dependencies properties for the specified type with specific Framework metadata options
/// </summary>
/// <param name="type">A dependency object</param>
/// <param name="options">A set of flags that must be set</param>
/// <returns>An array of Dependency Properties.</returns>
internal static DependencyProperty[] GetFrameworkPropertiesForType(Type type, FrameworkPropertyMetadataOptions options)
internal static DependencyProperty[] GetInheritedPropertiesForType(Type type)
{
DependencyProperty[] result = null;
var key = CachedTuple.Create(type, options);

if (!_getFrameworkPropertiesForType.TryGetValue(key, out result))
if (!_getInheritedPropertiesForType.TryGetValue(type, out result))
{
_getFrameworkPropertiesForType.Add(key, result = InternalGetFrameworkPropertiesForType(type, options));
_getInheritedPropertiesForType.Add(type, result = InternalGetInheritedPropertiesForType(type));
}

return result;
Expand All @@ -422,9 +403,8 @@ internal static DependencyProperty[] GetFrameworkPropertiesForType(Type type, Fr
internal static void ClearRegistry()
{
_registry.Clear();
_getPropertiesForType.Clear();
_getPropertyCache.Clear();
_getFrameworkPropertiesForType.Clear();
_getInheritedPropertiesForType.Clear();
}

private static void RegisterProperty(Type ownerType, string name, DependencyProperty newProperty)
Expand All @@ -434,29 +414,6 @@ private static void RegisterProperty(Type ownerType, string name, DependencyProp
_registry.Add(ownerType, name, newProperty);
}

private static DependencyProperty[] InternalGetPropertiesForType(Type type)
{
ForceInitializeTypeConstructor(type);

var results = new List<DependencyProperty>();

do
{
_registry.AppendPropertiesForType(type, results);

// Dependency properties are inherited
type = type.BaseType;
}
while (type != typeof(object) && type != null);

var array = results.ToArray();

// Produce a pre-sorted list, aligned with the initial behavior of DependencyPropertyDetailsCollection
Array.Sort(array, (l, r) => l.UniqueId - r.UniqueId);

return array;
}

/// <summary>
/// Forces the invocation of the cctor of a type and its base types that may contain DependencyProperty registrations.
/// </summary>
Expand All @@ -480,21 +437,27 @@ private static void ForceInitializeTypeConstructor(Type type)
while (type != null);
}

private static DependencyProperty[] InternalGetFrameworkPropertiesForType(Type type, FrameworkPropertyMetadataOptions options)
private static DependencyProperty[] InternalGetInheritedPropertiesForType(Type type)
{
var output = new List<DependencyProperty>();
ForceInitializeTypeConstructor(type);

var results = new List<DependencyProperty>();

foreach (var prop in GetPropertiesForType(type))
do
{
var propertyOptions = (prop.Metadata as FrameworkPropertyMetadata)?.Options;
_registry.AppendInheritedPropertiesForType(type, results);

if (propertyOptions != null && (propertyOptions & options) != 0)
{
output.Add(prop);
}
// Dependency properties are inherited
type = type.BaseType;
}
while (type != typeof(object) && type != null);

return output.ToArray();
var array = results.ToArray();

// Produce a pre-sorted list, aligned with the initial behavior of DependencyPropertyDetailsCollection
Array.Sort(array, (l, r) => l.UniqueId - r.UniqueId);

return array;
}

private bool TryGetDefaultInheritedPropertyValue(out object defaultValue)
Expand Down

0 comments on commit 69f9ef4

Please sign in to comment.