Skip to content

Commit

Permalink
Reduce IO a bit (#150)
Browse files Browse the repository at this point in the history
* Reduce IO a bit

Simple change to only open a file once in a few cases instead of 2 or 3
times

* more
  • Loading branch information
jaredpar committed Aug 14, 2024
1 parent 6fc6f8a commit cfebd0b
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 27 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,9 @@ ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog

# Compiler logs
*.complog

# NVidia Nsight GPU debugger configuration file
*.nvuser

Expand Down
15 changes: 15 additions & 0 deletions src/Basic.CompilerLog.UnitTests/RoslynUtilTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,19 @@ public void GetAssemblyFileName(string commandLine, string expectedFileName)
Assert.Equal(expectedFileName, actualFileName);
}

[Fact]
public void ReadMvidSimple()
{
var path = typeof(RoslynUtil).Assembly.Location;
var mvid = RoslynUtil.ReadMvid(path);
Assert.NotEqual(Guid.Empty, mvid);
}

[Fact]
public void ReadAssemblyNameSimple()
{
var path = typeof(RoslynUtil).Assembly.Location;
var name = RoslynUtil.ReadAssemblyName(path);
Assert.Equal("Basic.CompilerLog.Util", name);
}
}
14 changes: 8 additions & 6 deletions src/Basic.CompilerLog.Util/BinaryLogReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -356,11 +356,12 @@ private List<ReferenceData> ReadAllReferenceDataCore(IEnumerable<string> filePat
{
if (!_referenceDataCache.TryGetValue(filePath, out var data))
{
var identityData = RoslynUtil.ReadAssemblyIdentityData(filePath);
data = new ReferenceData(
filePath,
RoslynUtil.GetMvid(filePath),
RoslynUtil.ReadAssemblyName(filePath),
RoslynUtil.ReadAssemblyInformationalVersion(filePath),
identityData.Mvid,
identityData.AssemblyName,
identityData.AssemblyInformationalVersion,
File.ReadAllBytes(filePath));
_referenceDataCache[filePath] = data;
}
Expand All @@ -377,11 +378,12 @@ private List<RawAnalyzerData> ReadAllRawAnalyzerData(CommandLineArguments args)
{
if (!_rawAnalyzerDataCache.TryGetValue(analyzer.FilePath, out var data))
{
var identityData = RoslynUtil.ReadAssemblyIdentityData(analyzer.FilePath);
data = new RawAnalyzerData(
RoslynUtil.GetMvid(analyzer.FilePath),
identityData.Mvid,
analyzer.FilePath,
RoslynUtil.ReadAssemblyName(analyzer.FilePath),
RoslynUtil.ReadAssemblyInformationalVersion(analyzer.FilePath));
identityData.AssemblyName,
identityData.AssemblyInformationalVersion);
_rawAnalyzerDataCache[analyzer.FilePath] = data;
}
list.Add(data);
Expand Down
20 changes: 10 additions & 10 deletions src/Basic.CompilerLog.Util/CompilerLogBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public bool Return(MemoryStream stream)
}

private readonly Dictionary<Guid, (string FileName, AssemblyName AssemblyName)> _mvidToRefInfoMap = new();
private readonly Dictionary<string, (Guid mvid, string? assemblyName, string? assemblyInformationVersion)> _assemblyPathToMvidMap = new(PathUtil.Comparer);
private readonly Dictionary<string, (Guid Mvid, string? AssemblyName, string? AssemblyInformationVersion)> _assemblyPathToMvidMap = new(PathUtil.Comparer);
private readonly HashSet<string> _contentHashMap = new(PathUtil.Comparer);
private readonly Dictionary<string, (string AssemblyName, string? CommitHash)> _compilerInfoMap = new(PathUtil.Comparer);
private readonly DefaultObjectPool<MemoryStream> _memoryStreamPool = new(new MemoryStreamPoolPolicy(), maximumRetained: 5);
Expand Down Expand Up @@ -499,35 +499,35 @@ private void AddAnalyzers(CompilationDataPack dataPack, CommandLineArguments arg
{
if (_assemblyPathToMvidMap.TryGetValue(filePath, out var info))
{
Debug.Assert(_mvidToRefInfoMap.ContainsKey(info.mvid));
Debug.Assert(_mvidToRefInfoMap.ContainsKey(info.Mvid));
return info;
}

using var fileStream = RoslynUtil.OpenBuildFileForRead(filePath);
info.mvid = RoslynUtil.GetMvid(fileStream);
info.assemblyName = RoslynUtil.ReadAssemblyName(filePath);
info.assemblyInformationVersion = RoslynUtil.ReadAssemblyInformationalVersion(filePath);
var identityData = RoslynUtil.ReadAssemblyIdentityData(filePath);
info.Mvid = identityData.Mvid;
info.AssemblyName = identityData.AssemblyName;
info.AssemblyInformationVersion = identityData.AssemblyInformationalVersion;

_assemblyPathToMvidMap[filePath] = info;

// If the assembly was already loaded from a different path then no more
// work is needed here
if (_mvidToRefInfoMap.ContainsKey(info.mvid))
if (_mvidToRefInfoMap.ContainsKey(info.Mvid))
{
return info;
}

var entry = ZipArchive.CreateEntry(GetAssemblyEntryName(info.mvid), CompressionLevel.Fastest);
var entry = ZipArchive.CreateEntry(GetAssemblyEntryName(info.Mvid), CompressionLevel.Fastest);
using var entryStream = entry.Open();
fileStream.Position = 0;
using var fileStream = RoslynUtil.OpenBuildFileForRead(filePath);
fileStream.CopyTo(entryStream);

// There are some assemblies for which MetadataReader will return an AssemblyName which
// fails ToString calls which is why we use AssemblyName.GetAssemblyName here.
//
// Example: .nuget\packages\microsoft.visualstudio.interop\17.2.32505.113\lib\net472\Microsoft.VisualStudio.Interop.dll
var assemblyName = AssemblyName.GetAssemblyName(filePath);
_mvidToRefInfoMap[info.mvid] = (Path.GetFileName(filePath), assemblyName);
_mvidToRefInfoMap[info.Mvid] = (Path.GetFileName(filePath), assemblyName);
return info;
}

Expand Down
34 changes: 23 additions & 11 deletions src/Basic.CompilerLog.Util/RoslynUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -268,16 +268,16 @@ internal static FileStream OpenBuildFileForRead(string filePath)
return new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
}

internal static Guid GetMvid(string filePath)
internal static Guid ReadMvid(string filePath)
{
using var file = OpenBuildFileForRead(filePath);
return GetMvid(file);
using var stream = OpenBuildFileForRead(filePath);
using var reader = new PEReader(stream, PEStreamOptions.LeaveOpen);
var mdReader = reader.GetMetadataReader();
return ReadMvid(mdReader);
}

internal static Guid GetMvid(Stream stream)
internal static Guid ReadMvid(MetadataReader mdReader)
{
using var reader = new PEReader(stream, PEStreamOptions.LeaveOpen);
var mdReader = reader.GetMetadataReader();
GuidHandle handle = mdReader.GetModuleDefinition().Mvid;
return mdReader.GetGuid(handle);
}
Expand Down Expand Up @@ -606,16 +606,16 @@ static int GetNewlineLength(Span<char> span) =>
return ReadStringAssemblyAttribute(assemblyFilePath, "CommitHashAttribute");
}

internal static string? ReadAssemblyInformationalVersion(string assemblyFilePath)
{
return ReadStringAssemblyAttribute(assemblyFilePath, nameof(AssemblyInformationalVersionAttribute));
}

private static string? ReadStringAssemblyAttribute(string assemblyFilePath, string attributeName)
{
using var stream = new FileStream(assemblyFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
using var peReader = new PEReader(stream);
var metadataReader = peReader.GetMetadataReader();
return ReadStringAssemblyAttribute(metadataReader, attributeName);
}

private static string? ReadStringAssemblyAttribute(MetadataReader metadataReader, string attributeName)
{
var attributes = metadataReader.GetAssemblyDefinition().GetCustomAttributes();
foreach (var attributeHandle in attributes)
{
Expand Down Expand Up @@ -644,4 +644,16 @@ static int GetNewlineLength(Span<char> span) =>
{
return MetadataReader.GetAssemblyName(assemblyFilePath).Name;
}

internal static (Guid Mvid, string? AssemblyName, string? AssemblyInformationalVersion) ReadAssemblyIdentityData(string assemblyFilePath)
{
using var stream = OpenBuildFileForRead(assemblyFilePath);
using var peReader = new PEReader(stream);
var metadataReader = peReader.GetMetadataReader();
var def = metadataReader.GetAssemblyDefinition();
var assemblyName = def.GetAssemblyName().Name;
var mvid = ReadMvid(metadataReader);
var assemblyInformationalVersion = ReadStringAssemblyAttribute(metadataReader, nameof(AssemblyInformationalVersionAttribute));
return (mvid, assemblyName, assemblyInformationalVersion);
}
}

0 comments on commit cfebd0b

Please sign in to comment.