Skip to content

Commit

Permalink
Add caching for type lookup of runtime class name, to address excepti…
Browse files Browse the repository at this point in the history
…on storm perf issue (#828)
  • Loading branch information
Scottj1s authored Apr 28, 2021
1 parent da45411 commit ef2472e
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 14 deletions.
17 changes: 3 additions & 14 deletions src/WinRT.Runtime/ComWrappersSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,13 +264,8 @@ internal static Func<IInspectable, object> CreateTypedRcwFactory(string runtimeC
return (IInspectable obj) => new ABI.System.Nullable<Type>(obj.ObjRef);
}

Type implementationType = null;

try
{
(implementationType, _) = TypeNameSupport.FindTypeByName(runtimeClassName.AsSpan());
}
catch (TypeLoadException)
Type implementationType = TypeNameSupport.FindTypeByNameCached(runtimeClassName);
if(implementationType == null)
{
// If we reach here, then we couldn't find a type that matches the runtime class name.
// Fall back to using IInspectable directly.
Expand Down Expand Up @@ -318,13 +313,7 @@ internal static string GetRuntimeClassForTypeCreation(IInspectable inspectable,
Type implementationType = null;
if (!string.IsNullOrEmpty(runtimeClassName))
{
try
{
(implementationType, _) = TypeNameSupport.FindTypeByName(runtimeClassName.AsSpan());
}
catch (TypeLoadException)
{
}
implementationType = TypeNameSupport.FindTypeByNameCached(runtimeClassName);
}

if (!(implementationType != null &&
Expand Down
23 changes: 23 additions & 0 deletions src/WinRT.Runtime/TypeNameSupport.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
Expand All @@ -25,12 +26,34 @@ enum TypeNameGenerationFlags
static class TypeNameSupport
{
private static List<Assembly> projectionAssemblies = new List<Assembly>();
private static ConcurrentDictionary<string, Type> typeNameCache = new ConcurrentDictionary<string, Type>() { ["TrackerCollection<T>"] = null };

public static void RegisterProjectionAssembly(Assembly assembly)
{
projectionAssemblies.Add(assembly);
}

/// <summary>
/// Parses and loads the given type name, if not found in the cache.
/// </summary>
/// <param name="runtimeClassName">The runtime class name to attempt to parse.</param>
/// <returns>The type, if found. Null otherwise</returns>
public static Type FindTypeByNameCached(string runtimeClassName)
{
return typeNameCache.GetOrAdd(runtimeClassName, (runtimeClassName) =>
{
Type implementationType = null;
try
{
implementationType = FindTypeByName(runtimeClassName.AsSpan()).type;
}
catch (Exception)
{
}
return implementationType;
});
}

/// <summary>
/// Parse the first full type name within the provided span.
/// </summary>
Expand Down

0 comments on commit ef2472e

Please sign in to comment.