Skip to content

Commit

Permalink
perf(Weaver): optimizing find file in assembly resolver (#925)
Browse files Browse the repository at this point in the history
  • Loading branch information
James-Frowen committed Sep 13, 2021
1 parent 09d8ba5 commit 68d6749
Showing 1 changed file with 20 additions and 10 deletions.
30 changes: 20 additions & 10 deletions Assets/Mirage/Weaver/PostProcessorAssemblyResolver.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -11,6 +11,7 @@ namespace Mirage.Weaver
class PostProcessorAssemblyResolver : IAssemblyResolver
{
private readonly string[] _assemblyReferences;
private readonly string[] _assemblyReferencesFileName;
private readonly Dictionary<string, AssemblyDefinition> _assemblyCache = new Dictionary<string, AssemblyDefinition>();
private readonly ICompiledAssembly _compiledAssembly;
private AssemblyDefinition _selfAssembly;
Expand All @@ -19,6 +20,8 @@ public PostProcessorAssemblyResolver(ICompiledAssembly compiledAssembly)
{
_compiledAssembly = compiledAssembly;
_assemblyReferences = compiledAssembly.References;
// cache paths here so we dont need to call it each time we resolve
_assemblyReferencesFileName = _assemblyReferences.Select(r => Path.GetFileName(r)).ToArray();
}


Expand Down Expand Up @@ -69,14 +72,20 @@ public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters p

private string FindFile(AssemblyNameReference name)
{
string fileName = _assemblyReferences.FirstOrDefault(r => Path.GetFileName(r) == name.Name + ".dll");
if (fileName != null)
return fileName;
// This method is called a lot, avoid linq

// perhaps the type comes from an exe instead
fileName = _assemblyReferences.FirstOrDefault(r => Path.GetFileName(r) == name.Name + ".exe");
if (fileName != null)
return fileName;
// first pass, check if we can find dll or exe file
string dllName = name.Name + ".dll";
string exeName = name.Name + ".exe";
for (int i = 0; i < _assemblyReferencesFileName.Length; i++)
{
// if filename matches, return full path
string fileName = _assemblyReferencesFileName[i];
if (fileName == dllName || fileName == exeName)
return _assemblyReferences[i];
}

// second pass (only run if first fails),

//Unfortunately the current ICompiledAssembly API only provides direct references.
//It is very much possible that a postprocessor ends up investigating a type in a directly
Expand All @@ -85,7 +94,8 @@ private string FindFile(AssemblyNameReference name)
//in the ILPostProcessing API. As a workaround, we rely on the fact here that the indirect references
//are always located next to direct references, so we search in all directories of direct references we
//got passed, and if we find the file in there, we resolve to it.
foreach (string parentDir in _assemblyReferences.Select(Path.GetDirectoryName).Distinct())
IEnumerable<string> allParentDirectories = _assemblyReferences.Select(Path.GetDirectoryName).Distinct();
foreach (string parentDir in allParentDirectories)
{
string candidate = Path.Combine(parentDir, name.Name + ".dll");
if (File.Exists(candidate))
Expand Down Expand Up @@ -133,4 +143,4 @@ public void AddAssemblyDefinitionBeingOperatedOn(AssemblyDefinition assemblyDefi
_selfAssembly = assemblyDefinition;
}
}
}
}

0 comments on commit 68d6749

Please sign in to comment.