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

Merge changes from a single DidChange notification #74268

Merged
merged 4 commits into from
Jul 25, 2024

Conversation

ToddGrun
Copy link
Contributor

@ToddGrun ToddGrun commented Jul 4, 2024

I'm currently investigating a customer profile where didChange notifications are showing very prevalently in CPU time. I've create this PR (#74267) to help with the underlying performance of creating the SourceText, however, there would still be potentially many source texts created for a single operation.

This PR attempts to alleviate that situation by changing the DidChange handler to create a single source text on the input TextDocumentContentChangeEvent array. This array can be quite large, such as when the user does a replace-all or multi-line edit in VS.

Roughly 50% of CPU time in the customer profile was spent in our DidChange handler (about 29 seconds of CPU time).

image

I'm currently investigating a customer profile where didChange notifications are showing very prevalently in CPU time. I've create this PR (dotnet#74267) to help with the underlying performance of creating the SourceText, however, there would still be potentially many source texts created for a single operation.

This PR attempts to alleviate that situation by changing the DidChange handler to create a single source text on the input TextDocumentContentChangeEvent array. This array can be quite large, such as when the user does a replace-all or multi-line edit in VS.

Roughly 50% of CPU time in the customer profile was spent in our DidChange handler (about 29 seconds of CPU time).
@ToddGrun ToddGrun requested a review from a team as a code owner July 4, 2024 01:35
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Infrastructure untriaged Issues and PRs which have not yet been triaged by a lead labels Jul 4, 2024
@@ -243,5 +243,20 @@ private static bool TryGetVSCompletionListSetting(ClientCapabilities clientCapab

return true;
}

public static int CompareTo(this Position p1, Position p2)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

CompareTo

I'm sure there is a similar method implemented somewhere in Roslyn, but I couldn't find it

@ToddGrun
Copy link
Contributor Author

@dotnet/roslyn-ide -- ptal

1 similar comment
@ToddGrun
Copy link
Contributor Author

@dotnet/roslyn-ide -- ptal

@ToddGrun
Copy link
Contributor Author

@dibarbet or @CyrusNajmabadi -- ptal

@ToddGrun
Copy link
Contributor Author

@dotnet/roslyn-ide -- ptal

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.

sorry, somehow this one slipped passed me

// If the host sends us changes in a way such that no earlier change can affect the position of a later change,
// then we can merge the changes into a single TextChange, allowing creation of only a single new
// source text.
for (var i = 1; i < contentChanges.Length; i++)
Copy link
Member

Choose a reason for hiding this comment

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

can we add some tests for this (e.g. sending changes that overlap and don't overlap and verifying that the server ends up with the correct source text?

Probably here - https://github.com/dotnet/roslyn/blob/fa05fe407b8b41eeade24e75f6e3746720bda927/src/LanguageServer/ProtocolUnitTests/DocumentChanges/DocumentChangesTests.cs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added some unit tests, they aren't as clean as I had hoped, but it should at least give some coverage


context.UpdateTrackedDocument(request.TextDocument.Uri, text);
if (prevChange.Range.Start.CompareTo(curChange.Range.End) < 0)
Copy link
Member

Choose a reason for hiding this comment

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

Its early and I'm not 100% sure of this. Is it possible we need to compare against all previous changes? For example we have two disparate changes, then one afterwards that overlaps just the first one?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Chatted in person, let me know if you still have concerns.

@ToddGrun
Copy link
Contributor Author

@dibarbet -- any remaining concerns?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Infrastructure 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.

3 participants