Adjust type finder and adds benchmark

This commit is contained in:
Shannon
2020-03-11 15:28:08 +11:00
parent 66cd25d8f5
commit 3bfa2e76cb
4 changed files with 69 additions and 19 deletions

View File

@@ -16,6 +16,13 @@ namespace Umbraco.Core.Composing
{
private readonly ILogger _logger;
private readonly IAssemblyProvider _assemblyProvider;
private volatile HashSet<Assembly> _localFilteredAssemblyCache;
private readonly object _localFilteredAssemblyCacheLocker = new object();
private readonly List<string> _notifiedLoadExceptionAssemblies = new List<string>();
private static readonly ConcurrentDictionary<string, Type> TypeNamesCache = new ConcurrentDictionary<string, Type>();
private readonly string[] _assembliesAcceptingLoadExceptions;
internal bool QueryWithReferencingAssemblies = true;
public TypeFinder(ILogger logger, IAssemblyProvider assemblyProvider, ITypeFinderConfig typeFinderConfig = null)
{
@@ -24,12 +31,6 @@ namespace Umbraco.Core.Composing
_assembliesAcceptingLoadExceptions = typeFinderConfig?.AssembliesAcceptingLoadExceptions.Where(x => !x.IsNullOrWhiteSpace()).ToArray() ?? Array.Empty<string>();
}
private volatile HashSet<Assembly> _localFilteredAssemblyCache;
private readonly object _localFilteredAssemblyCacheLocker = new object();
private readonly List<string> _notifiedLoadExceptionAssemblies = new List<string>();
private static readonly ConcurrentDictionary<string, Type> TypeNamesCache= new ConcurrentDictionary<string, Type>();
private readonly string[] _assembliesAcceptingLoadExceptions;
private bool AcceptsLoadExceptions(Assembly a)
{
if (_assembliesAcceptingLoadExceptions.Length == 0)
@@ -268,18 +269,24 @@ namespace Umbraco.Core.Composing
var stack = new Stack<Assembly>();
stack.Push(attributeType.Assembly);
if (!QueryWithReferencingAssemblies)
{
foreach (var a in candidateAssemblies)
stack.Push(a);
}
while (stack.Count > 0)
{
var assembly = stack.Pop();
Type[] assemblyTypes = null;
IReadOnlyList<Type> assemblyTypes = null;
if (assembly != attributeType.Assembly || attributeAssemblyIsCandidate)
{
// get all assembly types that can be assigned to baseType
try
{
assemblyTypes = GetTypesWithFormattedException(assembly)
.ToArray(); // in try block
.ToList(); // in try block
}
catch (TypeLoadException ex)
{
@@ -299,10 +306,13 @@ namespace Umbraco.Core.Composing
if (assembly != attributeType.Assembly && assemblyTypes.Where(attributeType.IsAssignableFrom).Any() == false)
continue;
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
if (QueryWithReferencingAssemblies)
{
candidateAssemblies.Remove(referencing);
stack.Push(referencing);
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
{
candidateAssemblies.Remove(referencing);
stack.Push(referencing);
}
}
}
@@ -333,19 +343,25 @@ namespace Umbraco.Core.Composing
var stack = new Stack<Assembly>();
stack.Push(baseType.Assembly);
if (!QueryWithReferencingAssemblies)
{
foreach (var a in candidateAssemblies)
stack.Push(a);
}
while (stack.Count > 0)
{
var assembly = stack.Pop();
// get all assembly types that can be assigned to baseType
Type[] assemblyTypes = null;
IReadOnlyList<Type> assemblyTypes = null;
if (assembly != baseType.Assembly || baseTypeAssemblyIsCandidate)
{
try
{
assemblyTypes = GetTypesWithFormattedException(assembly)
.Where(baseType.IsAssignableFrom)
.ToArray(); // in try block
.ToList(); // in try block
}
catch (TypeLoadException ex)
{
@@ -365,10 +381,13 @@ namespace Umbraco.Core.Composing
if (assembly != baseType.Assembly && assemblyTypes.All(x => x.IsSealed))
continue;
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
if (QueryWithReferencingAssemblies)
{
candidateAssemblies.Remove(referencing);
stack.Push(referencing);
foreach (var referencing in TypeHelper.GetReferencingAssemblies(assembly, candidateAssemblies))
{
candidateAssemblies.Remove(referencing);
stack.Push(referencing);
}
}
}

View File

@@ -82,9 +82,9 @@ namespace Umbraco.Core.Composing
/// If the assembly of the assignTypeFrom Type is in the App_Code assembly, then we return nothing since things cannot
/// reference that assembly, same with the global.asax assembly.
/// </remarks>
public static Assembly[] GetReferencingAssemblies(Assembly assembly, IEnumerable<Assembly> assemblies)
public static IReadOnlyList<Assembly> GetReferencingAssemblies(Assembly assembly, IEnumerable<Assembly> assemblies)
{
if (assembly.IsAppCodeAssembly() || assembly.IsGlobalAsaxAssembly())
if (assembly.IsDynamic || assembly.IsAppCodeAssembly() || assembly.IsGlobalAsaxAssembly())
return EmptyAssemblies;
@@ -92,7 +92,7 @@ namespace Umbraco.Core.Composing
// should only be scanning those assemblies because any other assembly will definitely not
// contain sub type's of the one we're currently looking for
var name = assembly.GetName().Name;
return assemblies.Where(x => x == assembly || HasReference(x, name)).ToArray();
return assemblies.Where(x => x == assembly || HasReference(x, name)).ToList();
}
/// <summary>

View File

@@ -0,0 +1,30 @@
using BenchmarkDotNet.Attributes;
using System;
using System.Linq;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Tests.Benchmarks.Config;
namespace Umbraco.Tests.Benchmarks
{
[MediumRunJob]
[MemoryDiagnoser]
public class TypeFinderBenchmarks
{
[Benchmark(Baseline = true)]
public void WithGetReferencingAssembliesCheck()
{
var typeFinder1 = new TypeFinder(new NullLogger(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
var found = typeFinder1.FindClassesOfType<IDiscoverable>().Count();
}
[Benchmark]
public void WithoutGetReferencingAssembliesCheck()
{
var typeFinder2 = new TypeFinder(new NullLogger(), new DefaultUmbracoAssemblyProvider(GetType().Assembly));
typeFinder2.QueryWithReferencingAssemblies = false;
var found = typeFinder2.FindClassesOfType<IDiscoverable>().Count();
}
}
}

View File

@@ -61,6 +61,7 @@
<Compile Include="SqlTemplatesBenchmark.cs" />
<Compile Include="StringReplaceManyBenchmarks.cs" />
<Compile Include="TryConvertToBenchmarks.cs" />
<Compile Include="TypeFinderBenchmarks.cs" />
<Compile Include="XmlBenchmarks.cs" />
</ItemGroup>
<ItemGroup>