Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup how we create skeleton assemblies. #57655

Merged
merged 8 commits into from
Nov 10, 2021

Conversation

CyrusNajmabadi
Copy link
Member

@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.

private static readonly ConditionalWeakTable<Compilation, SkeletonReferenceSet> s_compilationToReferenceMap = new();

private readonly object _gate = new();
private partial class CachedSkeletonReferences
Copy link
Member 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
Member 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
Member 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
Member 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