Skip to content

Commit

Permalink
Merge pull request #529 from microsoft/fixMemory
Browse files Browse the repository at this point in the history
Avoid mapping the metadata file more than once
  • Loading branch information
AArnott committed Apr 12, 2022
2 parents e525c05 + 054aabf commit 17a7887
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 4 deletions.
24 changes: 21 additions & 3 deletions src/Microsoft.Windows.CsWin32/MetadataIndex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Microsoft.Windows.CsWin32
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
Expand All @@ -20,6 +21,12 @@ internal class MetadataIndex : IDisposable
{
private static readonly Dictionary<CacheKey, Stack<MetadataIndex>> Cache = new();

/// <summary>
/// A cache of metadata files read.
/// All access to this should be within a <see cref="Cache"/> lock.
/// </summary>
private static readonly Dictionary<string, MemoryMappedFile> MetadataFiles = new(StringComparer.OrdinalIgnoreCase);

private readonly string metadataPath;

private readonly Platform? platform;
Expand All @@ -45,14 +52,14 @@ internal class MetadataIndex : IDisposable
/// </summary>
private readonly Dictionary<TypeDefinitionHandle, string> handleTypeReleaseMethod = new();

private MetadataIndex(string metadataPath, Platform? platform)
private MetadataIndex(string metadataPath, Stream metadataStream, Platform? platform)
{
this.metadataPath = metadataPath;
this.platform = platform;

try
{
this.metadataStream = File.OpenRead(metadataPath);
this.metadataStream = metadataStream;
this.peReader = new PEReader(this.metadataStream);
this.mr = this.peReader.GetMetadataReader();

Expand Down Expand Up @@ -230,16 +237,27 @@ public void Dispose()

internal static MetadataIndex Get(string metadataPath, Platform? platform)
{
metadataPath = Path.GetFullPath(metadataPath);
CacheKey key = new CacheKey(metadataPath, platform);
MemoryMappedViewStream metadataBytes;
lock (Cache)
{
if (Cache.TryGetValue(key, out Stack<MetadataIndex> stack) && stack.Count > 0)
{
return stack.Pop();
}

// Read the entire metadata file exactly once so that many MemoryStreams can share the memory.
if (!MetadataFiles.TryGetValue(metadataPath, out MemoryMappedFile? file))
{
file = MemoryMappedFile.CreateFromFile(metadataPath);
MetadataFiles.Add(metadataPath, file);
}

metadataBytes = file.CreateViewStream();
}

return new MetadataIndex(metadataPath, platform);
return new MetadataIndex(metadataPath, metadataBytes, platform);
}

internal static void Return(MetadataIndex index)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" />
<PackageReference Include="Microsoft.Windows.SDK.Win32Metadata" Version="$(MetadataVersion)" GeneratePathProperty="true" PrivateAssets="none" />
<PackageReference Include="Microsoft.Windows.SDK.Win32Docs" Version="$(ApiDocsVersion)" GeneratePathProperty="true" PrivateAssets="none" />
<PackageReference Include="Nullable" Version="1.3.0" />
<PackageReference Include="System.Memory" Version="4.5.4" PrivateAssets="none" />
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0" />
<PackageReference Include="System.Text.Encodings.Web" Version="4.7.2" />
Expand Down

0 comments on commit 17a7887

Please sign in to comment.