Skip to content

Commit 9911e09

Browse files
author
Stewart Miles
committed
Reduce memory allocation caused by VersionHandler.FindClass().
VersionHandler.FindClass() is called a lot throughout the plugin so this commit changes the method to memoize the result of each query to remove any allocation from future searches for the same class. Some searches would allocate ~500kb, this eliminates this allocation entirely. Issue googlesamples#146 Bug: 121162585 Change-Id: I28c3ddcdce8d2c9645677ca6bbd11acdaa2ed626
1 parent e6d3a26 commit 9911e09

File tree

1 file changed

+32
-11
lines changed

1 file changed

+32
-11
lines changed

source/VersionHandler/src/VersionHandler.cs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ public class VersionHandler {
4545
// File which contains the set of methods to call when an update operation is complete.
4646
const string CALLBACKS_PATH = "Temp/VersionHandlerCallbacks";
4747

48+
// Enumerating over loaded assemblies and retrieving each name is pretty expensive (allocates
49+
// ~2Kb per call multiplied by number of assemblies (i.e > 50)). This leads to memory being
50+
// allocated that needs to be garbage collected which can reduce performance of the editor.
51+
// This caches any found types for each combined assembly name + class name. Once a class
52+
// is found this dictionary retains a reference to the type.
53+
private static Dictionary<string, Type> typeCache = new Dictionary<string, Type>();
54+
4855
// Get the VersionHandler implementation class.
4956
private static Type Impl {
5057
get { return FindClass(VERSION_HANDLER_ASSEMBLY_NAME, VERSION_HANDLER_IMPL_CLASS); }
@@ -410,21 +417,35 @@ private static object InvokeImplMethod(string methodName, object[] args = null,
410417
/// <param name="className">Name of the class to find.</param>
411418
/// <returns>The Type of the class if found, null otherwise.</returns>
412419
public static Type FindClass(string assemblyName, string className) {
413-
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) {
414-
if (!String.IsNullOrEmpty(assemblyName)) {
415-
if (assembly.GetName().Name == assemblyName) {
416-
return Type.GetType(className + ", " + assembly.FullName);
417-
}
418-
} else {
419-
// Search for the first instance of a class matching this name in all assemblies.
420-
foreach (var type in assembly.GetTypes()) {
421-
if (type.FullName == className) {
422-
return type;
420+
Type type;
421+
bool hasAssemblyName = !String.IsNullOrEmpty(assemblyName);
422+
string fullName = hasAssemblyName ? className + ", " + assemblyName : className;
423+
if (typeCache.TryGetValue(fullName, out type)) {
424+
return type;
425+
}
426+
type = Type.GetType(fullName);
427+
if (type == null) {
428+
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) {
429+
if (hasAssemblyName) {
430+
if (assembly.GetName().Name == assemblyName) {
431+
type = Type.GetType(className + ", " + assembly.FullName);
432+
break;
433+
}
434+
} else {
435+
// Search for the first instance of a class matching this name in all
436+
// assemblies.
437+
foreach (var currentType in assembly.GetTypes()) {
438+
if (type.FullName == className) {
439+
type = currentType;
440+
}
423441
}
442+
if (type != null) break;
424443
}
425444
}
445+
426446
}
427-
return null;
447+
if (type != null) typeCache[fullName] = type;
448+
return type;
428449
}
429450

430451
/// <summary>

0 commit comments

Comments
 (0)