Skip to content

Commit

Permalink
Merge pull request #75479 from CyrusNajmabadi/mvidCaching
Browse files Browse the repository at this point in the history
  • Loading branch information
CyrusNajmabadi authored Oct 23, 2024
2 parents 08243d3 + c64eab7 commit e7e5755
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ protected virtual Checksum CreateChecksum(AnalyzerReference reference)
{
case AnalyzerFileReference fileReference:
writer.WriteString(fileReference.FullPath);
writer.WriteGuid(IsolatedAnalyzerReferenceSet.TryGetAnalyzerFileReferenceMvid(fileReference));
writer.WriteGuid(IsolatedAnalyzerReferenceSet.TryGetFileReferenceMvid(fileReference.FullPath));
break;

case AnalyzerImageReference analyzerImageReference:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -82,7 +83,11 @@ internal sealed partial class IsolatedAnalyzerReferenceSet
/// </summary>
/// <remarks>Guarded by <see cref="s_gate"/>. Note that while the gate is static, this is instance data on the <see
/// cref="s_lastCreatedAnalyzerReferenceSet"/>. And we only want to mutate that instance data from one thread at a
/// time.</remarks>
/// time.
///
/// Stored as an <see cref="IReadOnlyList{T}"/> so this can safely be used as a key in caches that map from a list
/// of items to some value (for example in an <see cref="ConditionalWeakTable{TKey, TValue}"/>.
/// </remarks>
private readonly Dictionary<Checksum, ImmutableArray<AnalyzerReference>> _analyzerReferences = [];

private IsolatedAnalyzerReferenceSet(
Expand Down Expand Up @@ -304,7 +309,7 @@ static void PopulateFilePathToMvidMap(
// Can ignore all other analyzer reference types. This is only about analyzer references changing on disk.
var analyzerReference = GetUnderlyingAnalyzerReference(initialReference);
if (analyzerReference is AnalyzerFileReference analyzerFileReference)
pathToMvidMap[analyzerFileReference.FullPath] = TryGetAnalyzerFileReferenceMvid(analyzerFileReference);
pathToMvidMap[analyzerFileReference.FullPath] = TryGetFileReferenceMvid(analyzerFileReference.FullPath);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#if !NET

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ private static async ValueTask<ImmutableArray<AnalyzerReference>> DefaultCreateI
return await getReferencesAsync().ConfigureAwait(false);
}

public static Guid TryGetAnalyzerFileReferenceMvid(AnalyzerFileReference file)
public static Guid TryGetFileReferenceMvid(string filePath)
{
try
{
return AssemblyUtilities.ReadMvid(file.FullPath);
return AssemblyUtilities.ReadMvid(filePath);
}
catch
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Shared.Extensions;
Expand Down Expand Up @@ -568,16 +569,38 @@ public static Checksum GetOrCreate<TValue, TArg>(TValue value, Func<TValue, TArg
return StronglyTypedChecksumCache<TValue, Checksum>.GetOrCreate(value, checksumCreator, arg);
}

public static ChecksumCollection GetOrCreateChecksumCollection<TReference>(
ImmutableArray<TReference> references, ISerializerService serializer, CancellationToken cancellationToken) where TReference : class
{
// Grab the internal array from the immutable array. This is safe as the callers can't modify it, and we just
// want the internal reference object to use as the key in the cache.
return GetOrCreateChecksumCollection(
ImmutableCollectionsMarshal.AsArray(references)!, serializer, cancellationToken);
}

public static ChecksumCollection GetOrCreateChecksumCollection<TReference>(
IReadOnlyList<TReference> references, ISerializerService serializer, CancellationToken cancellationToken) where TReference : class
{
// Cache both at the list-of-references level...
return StronglyTypedChecksumCache<IReadOnlyList<TReference>, ChecksumCollection>.GetOrCreate(
references,
static (references, tuple) =>
{
var (serializer, cancellationToken) = tuple;
var checksums = new FixedSizeArrayBuilder<Checksum>(references.Count);
foreach (var reference in references)
checksums.Add(tuple.serializer.CreateChecksum(reference, tuple.cancellationToken));
{
// ... and cache at the individual reference level.
var checksum = GetOrCreate(
reference,
static (reference, arg) =>
{
var (serializer, cancellationToken) = arg;
return serializer.CreateChecksum(reference, cancellationToken);
},
arg: (serializer, cancellationToken));
checksums.Add(checksum);
}
return new ChecksumCollection(checksums.MoveToImmutable());
},
Expand Down

0 comments on commit e7e5755

Please sign in to comment.