Skip to content

Commit b1ddc8a

Browse files
authored
Merge pull request #9551 from h3xds1nz/dependency-property-hashtable-lock
Optimize DependencyProperty lookup/registration performance, remove allocs
2 parents a2b5880 + cb5ec16 commit b1ddc8a

File tree

1 file changed

+17
-35
lines changed

1 file changed

+17
-35
lines changed

src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/DependencyProperty.cs

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,10 @@ private static void RegisterParameterValidation(string name, Type propertyType,
257257

258258
private static DependencyProperty RegisterCommon(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback)
259259
{
260-
FromNameKey key = new FromNameKey(name, ownerType);
260+
FromNameKey key = new(name, ownerType);
261261
lock (Synchronized)
262262
{
263-
if (PropertyFromName.Contains(key))
263+
if (PropertyFromName.ContainsKey(key))
264264
{
265265
throw new ArgumentException(SR.Format(SR.PropertyAlreadyRegistered, name, ownerType.Name));
266266
}
@@ -761,11 +761,11 @@ public DependencyProperty AddOwner(Type ownerType, PropertyMetadata typeMetadata
761761

762762
// Map owner type to this property
763763
// Build key
764-
FromNameKey key = new FromNameKey(Name, ownerType);
764+
FromNameKey key = new(Name, ownerType);
765765

766766
lock (Synchronized)
767767
{
768-
if (PropertyFromName.Contains(key))
768+
if (PropertyFromName.ContainsKey(key))
769769
{
770770
throw new ArgumentException(SR.Format(SR.PropertyAlreadyRegistered, Name, ownerType.Name));
771771
}
@@ -776,13 +776,11 @@ public DependencyProperty AddOwner(Type ownerType, PropertyMetadata typeMetadata
776776
OverrideMetadata(ownerType, typeMetadata);
777777
}
778778

779-
780779
lock (Synchronized)
781780
{
782781
PropertyFromName[key] = this;
783782
}
784783

785-
786784
return this;
787785
}
788786

@@ -979,19 +977,17 @@ internal static DependencyProperty FromName(string name, Type ownerType)
979977
ArgumentNullException.ThrowIfNull(name);
980978
ArgumentNullException.ThrowIfNull(ownerType);
981979

982-
FromNameKey key = new FromNameKey(name, ownerType);
983-
984-
while ((dp == null) && (ownerType != null))
980+
while (ownerType != null)
985981
{
986982
// Ensure static constructor of type has run
987-
MS.Internal.WindowsBase.SecurityHelper.RunClassConstructor(ownerType);
983+
SecurityHelper.RunClassConstructor(ownerType);
988984

989985
// Locate property
990-
key.UpdateNameKey(ownerType);
991-
986+
FromNameKey key = new(name, ownerType);
992987
lock (Synchronized)
993988
{
994-
dp = (DependencyProperty)PropertyFromName[key];
989+
if (PropertyFromName.TryGetValue(key, out dp))
990+
return dp;
995991
}
996992

997993
ownerType = ownerType.BaseType;
@@ -1033,7 +1029,7 @@ internal static bool IsValidType(object value, Type propertyType)
10331029
return true;
10341030
}
10351031

1036-
private class FromNameKey
1032+
private readonly struct FromNameKey : IEquatable<FromNameKey>
10371033
{
10381034
public FromNameKey(string name, Type ownerType)
10391035
{
@@ -1043,39 +1039,25 @@ public FromNameKey(string name, Type ownerType)
10431039
_hashCode = _name.GetHashCode() ^ _ownerType.GetHashCode();
10441040
}
10451041

1046-
public void UpdateNameKey(Type ownerType)
1047-
{
1048-
_ownerType = ownerType;
1049-
1050-
_hashCode = _name.GetHashCode() ^ _ownerType.GetHashCode();
1051-
}
1052-
10531042
public override int GetHashCode()
10541043
{
10551044
return _hashCode;
10561045
}
10571046

10581047
public override bool Equals(object o)
10591048
{
1060-
if ((o != null) && (o is FromNameKey))
1061-
{
1062-
return Equals((FromNameKey)o);
1063-
}
1064-
else
1065-
{
1066-
return false;
1067-
}
1049+
return o is FromNameKey key && Equals(key);
10681050
}
10691051

10701052
public bool Equals(FromNameKey key)
10711053
{
1072-
return (_name.Equals(key._name) && (_ownerType == key._ownerType));
1054+
return _name.Equals(key._name) && _ownerType == key._ownerType;
10731055
}
10741056

1075-
private string _name;
1076-
private Type _ownerType;
1057+
private readonly string _name;
1058+
private readonly Type _ownerType;
10771059

1078-
private int _hashCode;
1060+
private readonly int _hashCode;
10791061
}
10801062

10811063

@@ -1198,13 +1180,13 @@ private enum Flags : int
11981180
/* property */ internal static ItemStructList<DependencyProperty> RegisteredPropertyList = new ItemStructList<DependencyProperty>(768);
11991181

12001182
// Synchronized: Covered by DependencyProperty.Synchronized
1201-
private static Hashtable PropertyFromName = new Hashtable();
1183+
private static readonly Dictionary<FromNameKey, DependencyProperty> PropertyFromName = new();
12021184

12031185
// Synchronized: Covered by DependencyProperty.Synchronized
12041186
private static int GlobalIndexCount;
12051187

12061188
// Global, cross-object synchronization
1207-
internal static object Synchronized = new object();
1189+
internal static readonly Lock Synchronized = new();
12081190

12091191
// Nullable Type
12101192
private static Type NullableType = typeof(Nullable<>);

0 commit comments

Comments
 (0)