From b2546c371ece2616153f375abd91f7d09d438cb4 Mon Sep 17 00:00:00 2001 From: Elizabeth Okerio Date: Mon, 15 Jan 2024 17:30:39 +0300 Subject: [PATCH] Perf Fix : GetPropertyValue (#1137) --- .../Value/TypedEdmStructuredObject.cs | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.AspNetCore.OData/Formatter/Value/TypedEdmStructuredObject.cs b/src/Microsoft.AspNetCore.OData/Formatter/Value/TypedEdmStructuredObject.cs index 468beb486..c86c3f5d3 100644 --- a/src/Microsoft.AspNetCore.OData/Formatter/Value/TypedEdmStructuredObject.cs +++ b/src/Microsoft.AspNetCore.OData/Formatter/Value/TypedEdmStructuredObject.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Reflection; using Microsoft.AspNetCore.OData.Common; @@ -20,8 +21,8 @@ namespace Microsoft.AspNetCore.OData.Formatter.Value /// internal abstract class TypedEdmStructuredObject : IEdmStructuredObject { - private static readonly ConcurrentDictionary, Func> _propertyGetterCache = - new ConcurrentDictionary, Func>(); + private static readonly ConcurrentDictionary<(string, Type), Func> _propertyGetterCache = + new ConcurrentDictionary<(string, Type), Func>(new PropertyGetterCacheEqualityComparer()); private IEdmStructuredTypeReference _edmType; private Type _type; @@ -88,7 +89,7 @@ internal static Func GetOrCreatePropertyGetter( IEdmStructuredTypeReference edmType, IEdmModel model) { - Tuple key = Tuple.Create(propertyName, type); + (string, Type) key = (propertyName, type); Func getter; if (!_propertyGetterCache.TryGetValue(key, out getter)) @@ -120,4 +121,37 @@ private static Func CreatePropertyGetter(Type type, string prope return helper.GetValue; } } + + /// + /// A custom equality comparer for the property getter cache. + /// + internal class PropertyGetterCacheEqualityComparer : IEqualityComparer<(string, Type)> + { + public bool Equals((string, Type) x, (string, Type) y) + { + return x.Item1 == y.Item1 && x.Item2 == y.Item2; + } + + /// + /// This method overrides the default GetHashCode() implementation + /// for a tuple of (string, Type) to provide a more effective hash code. + /// + /// The tuple object to calculate a hash code for + /// The calculated hash code. + public int GetHashCode((string, Type) obj) + { + unchecked + { + // The choice of 19 as the initial prime number is arbitrary but common in most hash code implementations. + // Multyplying by a prime number helps to reduce the chance of collisions. + // The hashcode of each tuple element is combined with the calculated hash to create + // a more unique hash code for the tuple. + int hash = 19; + hash = hash * 23 + obj.Item1.GetHashCode(); + hash = hash * 23 + obj.Item2.GetHashCode(); + + return hash; + } + } + } }