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

Remove BranchId from the workspace. #63578

Merged
merged 3 commits into from
Aug 25, 2022

Conversation

CyrusNajmabadi
Copy link
Member

Can choose to review this commit by commit, or just the end form.

The BranchId concept has always been somewhat suspect. It was a way of determining if the Solution instance you had was a Solution that had ever been teh .CurrentSolution of a workspace, or if you had a forked solution off of one of those solutions. Needing to know if you were one of these has never been clear as to why that's important. Roslyn operates in snapshots, and attempts to do so in a purely functional fashion. What does it matter if you were on a .CurrentSolution, or a fork of that, or a fork of that fork?

At one point we definitely used this when it came to persisting data. We didn't want analysis about a fork of a solution to overwrite data in our persistence service corresponding to the primary solution. However, that code went away ages ago when:

  1. we stopped storing diagnostic information in the persistence layer.
  2. we ensured that all persisted data is stored with a checksum.

At that point, there was no concern about overwriting data with something invalid.

This PR gets rid of hte BranchId concept entirely and fixes up any remaining stragglers to get off of it.

@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner August 24, 2022 19:56
@@ -130,9 +130,6 @@ private void OnWorkspaceChanged(object? sender, WorkspaceChangeEventArgs e)
private async ValueTask SynchronizePrimaryWorkspaceAsync(CancellationToken cancellationToken)
{
var solution = _workspace.CurrentSolution;
if (solution.BranchId != _workspace.PrimaryBranchId)
return;
Copy link
Member Author

Choose a reason for hiding this comment

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

totally unnecessary. we are always accessing _workspace.CurrentSolution above. So this solution was always the primary-branch solution.

private readonly ConditionalWeakTable<Solution, Solution> _designTimeToCompileTimeSolution = new();
#else
private ConditionalWeakTable<Solution, Solution> _designTimeToCompileTimeSolution = new();
#endif
Copy link
Member Author

Choose a reason for hiding this comment

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

.net core has ConditionalWeakTable.Clear(). Standard does not. So we simulate it by overwriting the field.

/// Cached compile time solution for a forked branch. This is used primarily by LSP cases where
/// we fork the workspace solution and request diagnostics for the forked solution.
/// </summary>
private (int DesignTimeSolutionVersion, BranchId DesignTimeSolutionBranch, Solution CompileTimeSolution)? _forkedBranchCompileTimeCache;
Copy link
Member Author

Choose a reason for hiding this comment

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

@dibarbet i believe this has the semantics from before. Previously we keyed basd on Version+BranchId. But these change every time you get a new solution. So the only time these woudl match would be if you passed in teh exact same (reference-equals) Solution instance from before. So we can get the same behavior by using a CWT keyed off Solution instances.

Copy link
Member

Choose a reason for hiding this comment

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

The idea here being that as soon as no one is using the solution we can get rid of the design time solution. Makes sense to me.

@@ -57,8 +57,7 @@ internal class DiagnosticComputer
_analysisKind = analysisKind;
_analyzerInfoCache = analyzerInfoCache;

// We only track performance from primary branch. All forked branch we don't care such as preview.
_performanceTracker = project.IsFromPrimaryBranch() ? project.Solution.Services.GetService<IPerformanceTrackerService>() : null;
_performanceTracker = project.Solution.Services.GetRequiredService<IPerformanceTrackerService>();
Copy link
Member Author

Choose a reason for hiding this comment

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

i don't see the value that in this. Why would it not matter what the performance was getting diagnostics in a preview workspace?

{
CheckNoChanges(oldSolution, newSolution);
return true;
}
Copy link
Member Author

@CyrusNajmabadi CyrusNajmabadi Aug 24, 2022

Choose a reason for hiding this comment

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

also not certain what teh value here is. If someone asks us to apply changes, we can simply walk through and figure out waht the changes were. This was a fast-bail-out for a case that seems like the unlikely one (e.g. when does someone ask to apply the same solution over the exisitng solution)?

we could choose to still haev a check like if (oldSolution == newSolution). but i question if htat has any value whatsoever given that newSolution.GetChanges(oldSolution) will just return an empty set of changes.

#if NETCOREAPP
_designTimeToCompileTimeSolution.Clear();
#else
_designTimeToCompileTimeSolution = 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.

note: doing the above seems unnecessary. as a CWT, they should naturally release their resources when they are no longer referenced anywhere.

@CyrusNajmabadi
Copy link
Member Author

@dibarbet @jasonmalinowski ptal.

/// Cached compile time solution for a forked branch. This is used primarily by LSP cases where
/// we fork the workspace solution and request diagnostics for the forked solution.
/// </summary>
private (int DesignTimeSolutionVersion, BranchId DesignTimeSolutionBranch, Solution CompileTimeSolution)? _forkedBranchCompileTimeCache;
Copy link
Member

Choose a reason for hiding this comment

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

The idea here being that as soon as no one is using the solution we can get rid of the design time solution. Makes sense to me.

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.

2 participants