Skip to content

Commit 6206842

Browse files
committed
perf: Improved performance in GenericTypesChecker and DictInitializer
1 parent 545b8b5 commit 6206842

File tree

12 files changed

+75
-38
lines changed

12 files changed

+75
-38
lines changed

Editor/AssemblyCreator/AssemblyCreatorHelper.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ private static ConstructorInfo AddComponentMenuConstructor
2727
null,
2828
new[] { typeof(string) },
2929
null);
30-
31-
Assert.IsNotNull(_addComponentMenuConstructor);
3230
}
3331

3432
return _addComponentMenuConstructor;
@@ -49,8 +47,6 @@ public static MethodInfo GetTypeFromHandle
4947
null,
5048
new[] { typeof(RuntimeTypeHandle) },
5149
null);
52-
53-
Assert.IsNotNull(_getTypeFromHandle);
5450
}
5551

5652
return _getTypeFromHandle;

Editor/AssemblyCreator/MenuItemsCreator.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ private static MethodInfo CreateAsset
3131
null,
3232
new[] { typeof(Type), typeof(string) },
3333
null);
34-
35-
Assert.IsNotNull(_createAsset);
3634
}
3735

3836
return _createAsset;
@@ -67,8 +65,6 @@ private static ConstructorInfo MenuItemConstructor
6765
null,
6866
new[] { typeof(string) },
6967
null);
70-
71-
Assert.IsNotNull(_menuItemConstructor);
7268
}
7369

7470
return _menuItemConstructor;

Editor/Drawers/GenericUnityObjectHelper.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using SolidUtilities.Editor.Helpers;
55
using UnityEditor;
66
using UnityEngine;
7-
using UnityEngine.Assertions;
87
using Object = UnityEngine.Object;
98

109
/// <summary>

Editor/Drawers/TypeReferenceWithBaseTypesDrawer.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ internal class TypeReferenceWithBaseTypesDrawer : TypeReferencePropertyDrawer
1717

1818
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
1919
{
20-
Assert.IsNotNull(label);
21-
Assert.IsFalse(label == GUIContent.none);
20+
Assert.IsFalse(label is null || label == GUIContent.none);
2221
position = EditorGUI.PrefixLabel(position, label);
2322
DrawTypeReferenceField(position, property);
2423
}

Editor/GeneratedTypesDatabase/GenerationDatabase.Serialization.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ public void Initialize()
2929
if (_genericArgumentKeys != null)
3030
throw new InvalidOperationException("The asset is already initialized.");
3131

32-
if (! typeof(GenericTypeInfo).IsSerializable)
33-
throw new SerializationException($"Cannot initialize a database with {typeof(GenericTypeInfo)} because the type is not serializable.");
34-
3532
_argumentGenericTypesDict = new FastIterationDictionary<ArgumentInfo, List<GenericTypeInfo>>();
3633
_argumentsPool = new Pool<ArgumentInfo>();
3734
_genericTypeArgumentsDict = new FastIterationDictionary<GenericTypeInfo, List<ConcreteClass>>();

Editor/GeneratedTypesDatabase/GenerationDatabase.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ internal abstract partial class GenerationDatabase<TUnityObject> :
4646

4747
public GenericTypeInfo[] InstanceGenericTypes => _genericTypeArgumentsDict.KeysCollection;
4848

49+
[CanBeNull]
50+
public static string GetCachedGenericTypeGUID(string typeNameAndAssembly)
51+
=> Instance._genericTypesPool.GetGUID(typeNameAndAssembly);
52+
4953
public static void AddGenericType(GenericTypeInfo genericTypeInfo)
5054
{
5155
Instance.AddGenericTypeImpl(genericTypeInfo);
@@ -60,7 +64,7 @@ public void AddGenericTypeImpl(GenericTypeInfo genericTypeInfo)
6064

6165
public static void AddConcreteClass(Type genericTypeWithoutArgs, Type[] genericArgs, string assemblyGUID)
6266
{
63-
var genericTypeInfo = new GenericTypeInfo(genericTypeWithoutArgs);
67+
var genericTypeInfo = GenericTypeInfo.Instantiate<TUnityObject>(genericTypeWithoutArgs);
6468

6569
int genericArgsLength = genericArgs.Length;
6670
var arguments = new ArgumentInfo[genericArgsLength];

Editor/GeneratedTypesDatabase/Pool.cs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,39 @@
22
{
33
using System;
44
using System.Collections.Generic;
5+
using JetBrains.Annotations;
56

67
internal class Pool<T>
8+
where T : TypeInfo
79
{
810
private readonly Dictionary<T, T> _dict;
11+
private readonly Dictionary<string, string> _typeNameGUIDDict;
912

1013
public Pool(int capacity = 0)
1114
{
1215
_dict = new Dictionary<T, T>(capacity);
16+
_typeNameGUIDDict = new Dictionary<string, string>(capacity);
1317
}
1418

1519
public T GetOrAdd(T item)
1620
{
1721
if (_dict.TryGetValue(item, out T existingItem))
1822
return existingItem;
1923

20-
_dict[item] = item;
24+
_dict.Add(item, item);
25+
_typeNameGUIDDict.Add(item.TypeNameAndAssembly, item.GUID);
2126
return item;
2227
}
2328

2429
public void AddRange(T[] items)
2530
{
2631
foreach (T item in items)
2732
{
28-
if (! _dict.ContainsKey(item))
29-
_dict.Add(item, item);
33+
if (_dict.ContainsKey(item))
34+
continue;
35+
36+
_dict.Add(item, item);
37+
_typeNameGUIDDict.Add(item.TypeNameAndAssembly, item.GUID);
3038
}
3139
}
3240

@@ -36,11 +44,20 @@ public void ChangeItem(ref T item, Action<T> changeItem)
3644
{
3745
item = existingItem;
3846
_dict.Remove(item);
47+
_typeNameGUIDDict.Remove(item.TypeNameAndAssembly);
3948
}
4049

4150
changeItem(item);
4251

43-
_dict[item] = item;
52+
_dict.Add(item, item);
53+
_typeNameGUIDDict.Add(item.TypeNameAndAssembly, item.GUID);
54+
}
55+
56+
[CanBeNull]
57+
public string GetGUID(string typeNameAndAssembly)
58+
{
59+
_typeNameGUIDDict.TryGetValue(typeNameAndAssembly, out string guid);
60+
return guid;
4461
}
4562
}
4663
}

Editor/GeneratedTypesDatabase/TypeInfo/GenericTypeInfo.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{
33
using System;
44
using System.Linq;
5+
using GenericUnityObjects.Util;
56
using NUnit.Framework;
67
using SolidUtilities.Helpers;
78
using UnityEngine;
@@ -29,13 +30,26 @@ public GenericTypeInfo(string typeFullName, string assemblyName, string guid, st
2930
_argNames = argNames;
3031
}
3132

32-
public GenericTypeInfo(Type type, string typeGUID = null)
33-
: base(type, typeGUID)
33+
private GenericTypeInfo(Type type, string typeNameAndAssembly, string guid)
34+
: base(type, typeNameAndAssembly, guid)
3435
{
36+
// Assert can be expensive when called many times, and there may be hundreds of GenericTypeInfos in
37+
// a large project that are constructed after each domain reload.
38+
#if GENERIC_UNITY_OBJECTS_DEBUG
3539
Assert.IsTrue(type.IsGenericTypeDefinition);
40+
#endif
41+
3642
_argNames = type.GetGenericArguments().Select(argType => argType.Name).ToArray();
3743
}
3844

45+
public static GenericTypeInfo Instantiate<TObject>(Type type)
46+
where TObject : UnityEngine.Object
47+
{
48+
string typeNameAndAssembly = TypeUtility.GetTypeNameAndAssembly(type);
49+
string guid = GenerationDatabase<TObject>.GetCachedGenericTypeGUID(typeNameAndAssembly);
50+
return new GenericTypeInfo(type, typeNameAndAssembly, guid);
51+
}
52+
3953
public void UpdateArgNames(string[] newNames) => _argNames = newNames;
4054

4155
public void UpdateArgNames(Type[] newTypes)

Editor/GeneratedTypesDatabase/TypeInfo/TypeInfo.cs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,20 @@ protected TypeInfo(Type type, string typeGUID = null)
3333
_guid = typeGUID ?? GetClassGUID(type);
3434
}
3535

36+
protected TypeInfo(Type type, string typeNameAndAssembly, string typeGUID)
37+
{
38+
Type = type;
39+
_typeNameAndAssembly = typeNameAndAssembly;
40+
_guid = typeGUID ?? GetClassGUID(type);
41+
}
42+
3643
private string GetClassGUID(Type type)
3744
{
45+
string guid = GenerationDatabase<MonoBehaviour>.GetCachedGenericTypeGUID(_typeNameAndAssembly);
46+
47+
if (guid != null)
48+
return guid;
49+
3850
if (TypeCannotHaveGUID())
3951
return string.Empty;
4052

@@ -56,7 +68,7 @@ public string TypeFullName
5668
}
5769
}
5870

59-
public bool RetrieveType<TObject>(out Type type, out bool retrievedFromGUID)
71+
public bool RetrieveType<TObject>(out Type type, out bool retrievedFromGUID, bool updateGUID = true)
6072
where TObject : Object
6173
{
6274
retrievedFromGUID = false;
@@ -71,8 +83,10 @@ public bool RetrieveType<TObject>(out Type type, out bool retrievedFromGUID)
7183

7284
if (Type != null)
7385
{
86+
if (updateGUID)
87+
UpdateGUIDIfNeeded<TObject>();
88+
7489
type = Type;
75-
UpdateGUIDIfNeeded<TObject>();
7690
return true;
7791
}
7892

@@ -89,10 +103,18 @@ public bool RetrieveType<TObject>(out Type type, out bool retrievedFromGUID)
89103
return Type != null;
90104
}
91105

92-
public Type RetrieveType<TObject>()
106+
/// <summary> Retrieves type stored in this <see cref="TypeInfo"/> instance. </summary>
107+
/// <param name="updateGUID">
108+
/// Whether to try updating GUID if the type was found using typeNameAndAssembly. It is strongly not
109+
/// recommended to use. The only case when it can be to false is after all generic types are updated, to
110+
/// improve performance. See <see cref="DictInitializer{TObject}"/>. /
111+
/// </param>
112+
/// <typeparam name="TObject"> Type derived from <see cref="UnityEngine.Object"/>. </typeparam>
113+
/// <returns> A retrieved type or <c>null</c>, if the type was not found by typeNameAndAssembly or GUID. </returns>
114+
public Type RetrieveType<TObject>(bool updateGUID = true)
93115
where TObject : Object
94116
{
95-
RetrieveType<TObject>(out Type type, out bool _);
117+
RetrieveType<TObject>(out Type type, out bool _, updateGUID);
96118
return type;
97119
}
98120

@@ -106,27 +128,21 @@ public void UpdateNameAndAssembly(Type newType) =>
106128

107129
public bool Equals(TypeInfo p)
108130
{
109-
// If parameter is null, return false.
110131
if (ReferenceEquals(p, null))
111132
{
112133
return false;
113134
}
114135

115-
// Optimization for a common success case.
116136
if (ReferenceEquals(this, p))
117137
{
118138
return true;
119139
}
120140

121-
// If run-time types are not exactly the same, return false.
122141
if (this.GetType() != p.GetType())
123142
{
124143
return false;
125144
}
126145

127-
// Return true if the fields match.
128-
// Note that the base class is not invoked because it is
129-
// System.Object, which defines Equals as reference equality.
130146
return TypeNameAndAssembly == p.TypeNameAndAssembly && _guid == p._guid;
131147
}
132148

@@ -184,7 +200,7 @@ private void UpdateGUIDIfNeeded<TObject>()
184200
if (TypeAtGUIDIsSame())
185201
return;
186202

187-
string newGUID = AssetSearcher.GetClassGUID(Type); //
203+
string newGUID = AssetSearcher.GetClassGUID(Type);
188204

189205
if (string.IsNullOrEmpty(newGUID) || GUID == newGUID)
190206
return;
@@ -199,14 +215,14 @@ private void UpdateGUIDIfNeeded<TObject>()
199215
}
200216
else
201217
{
202-
throw new TypeLoadException($"{nameof(UpdateGUIDIfNeeded)} method doesn't know of this inheritor of {nameof(TypeInfo)} yet: {GetType()}.");
218+
throw new TypeLoadException(
219+
$"{nameof(UpdateGUIDIfNeeded)} method doesn't know of this inheritor " +
220+
$"of {nameof(TypeInfo)} yet: {GetType()}.");
203221
}
204222
}
205223

206224
private bool TypeAtGUIDIsSame()
207225
{
208-
// Check if asset at guid contains the same type
209-
// If it doesn't contain the same type or no type at all, search GUID of the type elsewhere
210226
string path = AssetDatabase.GUIDToAssetPath(GUID);
211227
if (path.Length == 0)
212228
return false;

Editor/GenericTypesAnalyzer/DictInitializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public static void Initialize()
2626
{
2727
var concreteClasses = GenerationDatabase<TObject>.GetConcreteClasses(behaviourInfo);
2828

29-
Type behaviourType = behaviourInfo.RetrieveType<TObject>();
29+
Type behaviourType = behaviourInfo.RetrieveType<TObject>(false);
3030

3131
var concreteClassesDict = new Dictionary<Type[], Type>(concreteClasses.Length, default(TypeArrayComparer));
3232

0 commit comments

Comments
 (0)