Skip to content

Commit b4a8aab

Browse files
committed
speed up warm-up when encountering new types
1 parent 5376fe8 commit b4a8aab

File tree

4 files changed

+214
-83
lines changed

4 files changed

+214
-83
lines changed

src/FastCloner/Code/Extensions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ internal static class Extensions
55
#if MODERN
66

77
#else
8+
public static bool Contains(this string source, string value, StringComparison comparisonType)
9+
{
10+
if (source is null)
11+
throw new ArgumentNullException(nameof(source));
12+
if (value is null)
13+
throw new ArgumentNullException(nameof(value));
14+
15+
return source.IndexOf(value, comparisonType) >= 0;
16+
}
17+
818
public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue = default(TValue))
919
{
1020
return dictionary.TryGetValue(key, out TValue value) ? value : defaultValue;

src/FastCloner/Code/FastClonerCache.cs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,13 @@ private static bool CalculateHasSafeTypeOverrides()
213213
private static readonly ClrCache<object> deepClassToCache = new ClrCache<object>();
214214
private static readonly ClrCache<object> shallowClassToCache = new ClrCache<object>();
215215
private static readonly ConcurrentLazyCache<object> typeConvertCache = new ConcurrentLazyCache<object>();
216-
private static readonly GenericClrCache<Tuple<Type, string>, object?> fieldCache = new GenericClrCache<Tuple<Type, string>, object?>();
216+
private static readonly GenericClrCache<TypeNameKey, object?> fieldCache = new GenericClrCache<TypeNameKey, object?>();
217217
private static readonly ClrCache<Dictionary<string, Type>> ignoredEventInfoCache = new ClrCache<Dictionary<string, Type>>();
218218
private static readonly ClrCache<List<MemberInfo>> allMembersCache = new ClrCache<List<MemberInfo>>();
219219
private static readonly GenericClrCache<MemberInfo, CloneBehavior?> memberBehaviorCache = new GenericClrCache<MemberInfo, CloneBehavior?>();
220220
private static readonly ClrCache<bool> typeContainsIgnoredMembersCache = new ClrCache<bool>();
221+
private static readonly ClrCache<CloneBehavior?> attributedTypeBehaviorCache = new ClrCache<CloneBehavior?>();
222+
private static readonly ClrCache<bool> immutableCollectionStatusCache = new ClrCache<bool>();
221223
private static readonly ClrCache<object> specialTypesCache = new ClrCache<object>();
222224
private static readonly ClrCache<bool> isTypeSafeHandleCache = new ClrCache<bool>();
223225
private static readonly ClrCache<bool> anonymousTypeStatusCache = new ClrCache<bool>();
@@ -228,7 +230,8 @@ private static bool CalculateHasSafeTypeOverrides()
228230
private static readonly ClrCache<Type?> collectionPayloadTypeCache = new ClrCache<Type?>();
229231
private static readonly ClrCache<bool> compilerGeneratedTypeCache = new ClrCache<bool>();
230232

231-
public static object? GetOrAddField(Type type, string name, Func<Type, object?> valueFactory) => fieldCache.GetOrAdd(new Tuple<Type, string>(type, name), k => valueFactory(k.Item1));
233+
public static object? GetOrAddField(Type type, string name, Func<Type, object?> valueFactory)
234+
=> fieldCache.GetOrAdd(new TypeNameKey(type, name), k => valueFactory(k.Type));
232235
public static object? GetOrAddClass(Type type, Func<Type, object?> valueFactory) => classCache.GetOrAdd(type, valueFactory);
233236
public static TypeCloneMetadata GetOrAddTypeMetadata(Type type, Func<Type, TypeCloneMetadata> valueFactory) => typeMetadataCache.GetOrAdd(type, valueFactory);
234237
public static object? GetOrAddStructAsObject(Type type, Func<Type, object?> valueFactory) => structCache.GetOrAdd(type, valueFactory);
@@ -238,6 +241,10 @@ private static bool CalculateHasSafeTypeOverrides()
238241
public static Dictionary<string, Type> GetOrAddIgnoredEventInfo(Type type, Func<Type, Dictionary<string, Type>> valueFactory) => ignoredEventInfoCache.GetOrAdd(type, valueFactory);
239242
public static List<MemberInfo> GetOrAddAllMembers(Type type, Func<Type, List<MemberInfo>> valueFactory) => allMembersCache.GetOrAdd(type, valueFactory);
240243
public static CloneBehavior? GetOrAddMemberBehavior(MemberInfo memberInfo, Func<MemberInfo, CloneBehavior?> valueFactory) => memberBehaviorCache.GetOrAdd(memberInfo, valueFactory);
244+
public static CloneBehavior? GetOrAddAttributedTypeBehavior(Type type, Func<Type, CloneBehavior?> valueFactory)
245+
=> attributedTypeBehaviorCache.GetOrAdd(type, valueFactory);
246+
public static bool GetOrAddImmutableCollectionStatus(Type type, Func<Type, bool> valueFactory)
247+
=> immutableCollectionStatusCache.GetOrAdd(type, valueFactory);
241248
public static bool GetOrAddTypeContainsIgnoredMembers(Type type, Func<Type, bool> valueFactory)
242249
{
243250
return typeContainsIgnoredMembersCache.GetOrAdd(type, valueFactory);
@@ -268,6 +275,8 @@ public static void ClearCache()
268275
allMembersCache.Clear();
269276
memberBehaviorCache.Clear();
270277
typeContainsIgnoredMembersCache.Clear();
278+
attributedTypeBehaviorCache.Clear();
279+
immutableCollectionStatusCache.Clear();
271280
specialTypesCache.Clear();
272281
isTypeSafeHandleCache.Clear();
273282
anonymousTypeStatusCache.Clear();
@@ -307,6 +316,36 @@ public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
307316

308317
public void Clear() => cache.Clear();
309318
}
319+
320+
private readonly struct TypeNameKey : IEquatable<TypeNameKey>
321+
{
322+
public TypeNameKey(Type type, string name)
323+
{
324+
Type = type;
325+
Name = name;
326+
}
327+
328+
public Type Type { get; }
329+
public string Name { get; }
330+
331+
public bool Equals(TypeNameKey other)
332+
{
333+
return ReferenceEquals(Type, other.Type) && Name == other.Name;
334+
}
335+
336+
public override bool Equals(object? obj)
337+
{
338+
return obj is TypeNameKey other && Equals(other);
339+
}
340+
341+
public override int GetHashCode()
342+
{
343+
unchecked
344+
{
345+
return (RuntimeHelpers.GetHashCode(Type) * 397) ^ Name.GetHashCode();
346+
}
347+
}
348+
}
310349

311350
private sealed class ConcurrentLazyCache<TValue>
312351
{

0 commit comments

Comments
 (0)