Browse Source

#2594: Cache LoadedAssembly.GetTargetFrameworkIdAsync, LoadedAssembly.GetRuntimePackAsync, PEFile.Name, PEFile.FullName to improve performance of assembly resolving. This improves performance of the analysis by a factor of 2.

pull/2595/head
Siegfried Pammer 3 years ago
parent
commit
e823ed9966
  1. 42
      ICSharpCode.Decompiler/Metadata/PEFile.cs
  2. 34
      ILSpy/LoadedAssembly.cs

42
ICSharpCode.Decompiler/Metadata/PEFile.cs

@ -72,8 +72,38 @@ namespace ICSharpCode.Decompiler.Metadata @@ -72,8 +72,38 @@ namespace ICSharpCode.Decompiler.Metadata
}
public bool IsAssembly => Metadata.IsAssembly;
public string Name => GetName();
public string FullName => IsAssembly ? Metadata.GetFullAssemblyName() : Name;
string? name;
public string Name {
get {
var value = LazyInit.VolatileRead(ref name);
if (value == null)
{
var metadata = Metadata;
value = metadata.IsAssembly
? metadata.GetString(metadata.GetAssemblyDefinition().Name)
: metadata.GetString(metadata.GetModuleDefinition().Name);
value = LazyInit.GetOrSet(ref name, value);
}
return value;
}
}
string? fullName;
public string FullName {
get {
var value = LazyInit.VolatileRead(ref fullName);
if (value == null)
{
var metadata = Metadata;
value = metadata.IsAssembly ? metadata.GetFullAssemblyName() : Name;
value = LazyInit.GetOrSet(ref fullName, value);
}
return value;
}
}
public TargetRuntime GetRuntime()
{
@ -98,14 +128,6 @@ namespace ICSharpCode.Decompiler.Metadata @@ -98,14 +128,6 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
string GetName()
{
var metadata = Metadata;
if (metadata.IsAssembly)
return metadata.GetString(metadata.GetAssemblyDefinition().Name);
return metadata.GetString(metadata.GetModuleDefinition().Name);
}
public ImmutableArray<AssemblyReference> AssemblyReferences => Metadata.AssemblyReferences.Select(r => new AssemblyReference(this, r)).ToImmutableArray();
public ImmutableArray<Resource> Resources => GetResources().ToImmutableArray();

34
ILSpy/LoadedAssembly.cs

@ -107,22 +107,41 @@ namespace ICSharpCode.ILSpy @@ -107,22 +107,41 @@ namespace ICSharpCode.ILSpy
this.ParentBundle = bundle;
}
string? targetFrameworkId;
/// <summary>
/// Returns a target framework identifier in the form '&lt;framework&gt;Version=v&lt;version&gt;'.
/// Returns an empty string if no TargetFrameworkAttribute was found or the file doesn't contain an assembly header, i.e., is only a module.
/// Returns an empty string if no TargetFrameworkAttribute was found
/// or the file doesn't contain an assembly header, i.e., is only a module.
///
/// Throws an exception if the file does not contain any .NET metadata (e.g. file of unknown format).
/// </summary>
public async Task<string> GetTargetFrameworkIdAsync()
{
var assembly = await GetPEFileAsync().ConfigureAwait(false);
return assembly.DetectTargetFrameworkId() ?? string.Empty;
var value = LazyInit.VolatileRead(ref targetFrameworkId);
if (value == null)
{
var assembly = await GetPEFileAsync().ConfigureAwait(false);
value = assembly.DetectTargetFrameworkId() ?? string.Empty;
value = LazyInit.GetOrSet(ref targetFrameworkId, value);
}
return value;
}
string? runtimePack;
public async Task<string> GetRuntimePackAsync()
{
var assembly = await GetPEFileAsync().ConfigureAwait(false);
return assembly.DetectRuntimePack() ?? string.Empty;
var value = LazyInit.VolatileRead(ref runtimePack);
if (value == null)
{
var assembly = await GetPEFileAsync().ConfigureAwait(false);
value = assembly.DetectRuntimePack() ?? string.Empty;
value = LazyInit.GetOrSet(ref runtimePack, value);
}
return value;
}
public ReferenceLoadInfo LoadedAssemblyReferencesInfo { get; } = new ReferenceLoadInfo();
@ -588,10 +607,9 @@ namespace ICSharpCode.ILSpy @@ -588,10 +607,9 @@ namespace ICSharpCode.ILSpy
var reader = module.Metadata;
if (reader == null || !reader.IsAssembly)
continue;
var asmDef = reader.GetAssemblyDefinition();
string tfm = await loaded.GetTargetFrameworkIdAsync();
string tfm = await loaded.GetTargetFrameworkIdAsync().ConfigureAwait(false);
string key = tfm + ";"
+ (shortNames ? reader.GetString(asmDef.Name) : reader.GetFullAssemblyName());
+ (shortNames ? module.Name : module.FullName);
if (!result.ContainsKey(key))
{
result.Add(key, module);

Loading…
Cancel
Save