Skip to content

Cleanup how we create skeleton assemblies.#57655

Merged
CyrusNajmabadi merged 8 commits intodotnet:mainfrom
CyrusNajmabadi:skeletonCleanup
Nov 10, 2021
Merged

Cleanup how we create skeleton assemblies.#57655
CyrusNajmabadi merged 8 commits intodotnet:mainfrom
CyrusNajmabadi:skeletonCleanup

Conversation

@CyrusNajmabadi
Copy link
Contributor

@CyrusNajmabadi CyrusNajmabadi commented Nov 9, 2021

Will comment the overall thrust of hte changes in the PR.

THis should be viewed with whitespace off.

Should be reviewed a commit at a time.

@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner November 9, 2021 19:56
@ghost ghost added the Area-IDE label Nov 9, 2021
private static readonly ConditionalWeakTable<Compilation, SkeletonReferenceSet> s_compilationToReferenceMap = new();

private readonly object _gate = new();
private partial class CachedSkeletonReferences
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this moved inside SolutionState so it could refer to ICompilationTracker.

@CyrusNajmabadi
Copy link
Contributor Author

@dibarbet can you ptal?

var metadataReference = TryGetReferenceSet(version)?.GetMetadataReference(properties);
if (metadataReference != null)
{
workspace.LogTestMessage($"Reusing the already cached skeleton assembly for {compilationTracker.ProjectState.Id}");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting, neve rseen LogTestMessage before - where do those messages go?

// being passed in. If so, we can just reuse what we already computed before.
var workspace = solution.Workspace;
var version = await compilationTracker.GetDependentSemanticVersionAsync(solution, cancellationToken).ConfigureAwait(false);
var metadataReference = TryGetReferenceSet(version)?.GetMetadataReference(properties);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the caching that is going on here is a bit confusing.

  1. we first look at the _skeletonReferenceSet from TryGetReferenceSet
  2. Assuming that isn't present, it goes to GetOrBuildReferenceSetAsync which immediately looks at the s_compilationToReferenceMap (in TryGetExistingReferenceSet) for the compilation with a note mentioning that we want to return the same instance for a compilation. Should 2) be done before 1)? Or is 2) done after to avoid looking at the compilation if not needed?
  3. TryGetExistingReferenceSet then calls TryGetReferenceSet, but we already looked at that in 1). Something doesn't add up

To me it is quite unclear which cache is preferred and when an item should be in s_compilationToReferenceMap vs. _skeletonReferenceSet

if (referenceSet != null)
return referenceSet;

storage = TryCreateMetadataStorage(workspace, compilation, cancellationToken);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there may be a race here?

  1. threadA hits line 163, enters the semaphore and starts creating the storage
  2. threadB hits line 163 while 1) is running and starts waiting
  3. threadA finishes creating the storage, exits the semaphore, but doesn't yet return the new skeleton references / update the fields
  4. threadB enters the semaphore, doesn't see the result from 3) since it isn't updated, and starts creating the same storage again.

Maybe the updating of the locals needs to happen in the semaphore as well

{
private readonly object _gate = new();
// Then see if we already have a reference set for this version. if so, we're done and can return that.
return TryGetReferenceSet(version);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as above the ordering seems weird. sometimes TryGetReferenceSet is called before the s_compilationToReferenceMap


using (Logger.LogBlock(FunctionId.Workspace_SkeletonAssembly_EmitMetadataOnlyImage, cancellationToken))
{
// TODO: make it to use SerializableBytes.WritableStream rather than MemoryStream so that
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this todo apply? looks like it's using SerializableBytes

/// <summary>
/// Use WeakReference so we don't keep MetadataReference's alive if they are not being consumed.
/// Note: if the weak-reference is actuall <see langword="null"/> (not that it points to null),
/// that means
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does it mean?!?! 😆

/// that means
/// Note: if the weak-reference is actually <see langword="null"/> (not that it points to null),
/// that means we know we were unable to generate a reference for those properties, and future
/// calls can early exit.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh... that's what it means 😆

Copy link
Member

@dibarbet dibarbet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as long as #57658 goes in

@CyrusNajmabadi
Copy link
Contributor Author

as long as #57658 goes in

Yup. I hate the CWT (and the logic around it). So it's going in for sure.

@CyrusNajmabadi CyrusNajmabadi merged commit e2012f1 into dotnet:main Nov 10, 2021
@ghost ghost added this to the Next milestone Nov 10, 2021
@CyrusNajmabadi CyrusNajmabadi deleted the skeletonCleanup branch November 10, 2021 20:01
@CyrusNajmabadi
Copy link
Contributor Author

I think there may be a race here?

fairly certain there is no race in the new PR> we'll look at that together.

@allisonchou allisonchou modified the milestones: Next, 17.1.P2 Nov 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants