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

Cache diagnostics produced during workspace pull, to avoid unnecessary computations #73201

Merged
merged 2 commits into from Apr 24, 2024

Conversation

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead labels Apr 23, 2024
@CyrusNajmabadi CyrusNajmabadi marked this pull request as ready for review April 23, 2024 21:33
@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner April 23, 2024 21:33
@CyrusNajmabadi
Copy link
Member Author

I have validated this fixes the issue.

private async ValueTask<ImmutableArray<DiagnosticData>> GetProjectDiagnosticsAsync(
IDiagnosticAnalyzerService diagnosticAnalyzerService, CancellationToken cancellationToken)
{
if (!s_projectToDiagnostics.TryGetValue(Document.Project, out var lazyDiagnostics))
Copy link
Member

Choose a reason for hiding this comment

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

Might be good to add a comment on s_projectToDiagnostics that parallel access won't happen because

  1. There is only one workspace diagnostic bucket that creates the AbstractWorkspaceDocumentDiagnosticSource
  2. the sources are called in order

Copy link
Member Author

Choose a reason for hiding this comment

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

Discussed offline. It's correct that parallel access won't happen. But it's also 100% ok if it does. CWT (and the pattern we use to access it here) is concurrency safe.

}
}

private async ValueTask<ImmutableArray<DiagnosticData>> GetProjectDiagnosticsAsync(
Copy link
Member

Choose a reason for hiding this comment

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

is it possible to add a test that verifies we're not analyzing twice? Maybe add a test-only analyzer that throws if called twice?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes. i acan try to add that.

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.

Approved, with the same comments as on #73201 (review)

@CyrusNajmabadi
Copy link
Member Author

@mavasani for eyes as well.

/// once we compute the diagnostics once for a particular project, we don't need to recompute them again as we
/// walk every document within it.
/// </summary>
private static readonly ConditionalWeakTable<Project, AsyncLazy<IReadOnlyList<DiagnosticData>>> s_projectToDiagnostics = new();
Copy link
Member Author

Choose a reason for hiding this comment

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

@mavasani i didn't want to do this, but caching at the IDiagnosticAnalyzerService just seems busted currently.

Document.Project.Solution, Document.Project.Id, documentId: null,
diagnosticIds: null, shouldIncludeAnalyzer,
// Ensure we compute and return diagnostics for both the normal docs and the additional docs in this project.
static (project, _) => [.. project.DocumentIds.Concat(project.AdditionalDocumentIds)],
Copy link
Member Author

Choose a reason for hiding this comment

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

@mavasani i needed to be able to do this as otherwise the built-in logic of the diag-analyzer-service is just to get the diagnostics for project.DocumentIds alone. I considered tweaking the core logic, but there were a fair amount of callers of GetDiagnosticsForIdsAsync and i was concerned that they might break if they started getting diags for additional-docs as well as normal docs.

@@ -76,7 +80,7 @@ public async Task<ImmutableArray<DiagnosticData>> GetDiagnosticsAsync(Cancellati
return GetDiagnosticData();
}

var documentIds = DocumentId != null ? [DocumentId] : project.DocumentIds;
Copy link
Member Author

Choose a reason for hiding this comment

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

@mavasani here is where we hardcoded that if you didn't pass in a document, you got only the diagnostics for the normal Documents (not including additional documents).

@CyrusNajmabadi CyrusNajmabadi merged commit 7a402c0 into dotnet:main Apr 24, 2024
25 checks passed
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Apr 24, 2024
@CyrusNajmabadi CyrusNajmabadi deleted the workspacePullCache branch April 24, 2024 02:39
@dibarbet dibarbet modified the milestones: Next, 17.11 P1 Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants