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

Use ITextDifferencingService.DiffSnapshotSpans instead of allocating full buffer text during codeaction previews #74114

Merged
merged 4 commits into from
Jun 26, 2024

Conversation

ToddGrun
Copy link
Contributor

This is enabled by changing ChangedSourceText to use the base class's ITextSnapshot based ctor instead of the ITextImage one. The base class then keeps a mapping of ITextImage -> ITextSnapshot, that can be used during the preview to map from a SourceText to an ITextSnapshot. Having the ITextSnapshot available allows the code to use the DiffService call that takes in SnapshotSpans instead of needing to allocate a string for the whole sourcetext.

The obvious concern here would be whether switching ChangedSourceText to have the ITextImage -> ITextSnapshot weakly kept is going to root the ITextSnapshot for longer than it would before. It appears that isn't too much of a worry though, as the SnapshotSourceText ctor that takes in the snapshot only uses it for the CWT mapping, and doesn't store it otherwise.

This shows as about 1.5% of allocations in the profile I took that brough up lightbulb/preview multiple times.

*** Previous allocations ***
image

…odeaction previews

This is enabled by changing ChangedSourceText to use the base class's ITextSnapshot based ctor instead of the ITextImage one. The base class then keeps a mapping of ITextImage -> ITextSnapshot, that can be used during the preview to map from a SourceText to an ITextSnapshot. Having the ITextSnapshot available allows the code to use the DiffService call that takes in SnapshotSpans instead of needing to allocate a string for the whole sourcetext.

The obvious concern here would be whether switching ChangedSourceText to have the ITextImage -> ITextSnapshot weakly kept is going to root the ITextSnapshot for longer than it would before. It appears that isn't too much of a worry though, as the SnapshotSourceText ctor that takes in the snapshot only uses it for the CWT mapping, and doesn't store it otherwise.
@@ -35,14 +35,14 @@ private class SnapshotSourceText : SourceText
private readonly Encoding? _encoding;
private readonly TextBufferContainer? _container;

private SnapshotSourceText(ITextBufferCloneService? textBufferCloneService, ITextSnapshot editorSnapshot, SourceHashAlgorithm checksumAlgorithm, TextBufferContainer container)
private SnapshotSourceText(ITextBufferCloneService? textBufferCloneService, ITextSnapshot editorSnapshot, Encoding? encoding, SourceHashAlgorithm checksumAlgorithm, TextBufferContainer container)
Copy link
Member

Choose a reason for hiding this comment

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

i'm missing the callsite that passed in a non-null value here. or was this just to make it explicit that all callsites are trying to pass that in?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The ChangedSourceText.ctor was previously calling the ITextImage version of this ctor, and passing in an encoding. I wanted to match that behavior.

var differenceOptions = new StringDifferenceOptions()
{
DifferenceType = StringDifferenceTypes.Line,
};
Copy link
Member

Choose a reason for hiding this comment

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

nit. make static readonly member of this type.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

? diffService.DiffSnapshotSpans(oldTextSnapshot!.GetFullSpan(), newTextSnapshot!.GetFullSpan(), differenceOptions)
: diffService.DiffStrings(oldText.ToString(), newText.ToString(), differenceOptions);

return diffResult;
Copy link
Member

Choose a reason for hiding this comment

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

nit: make extension on IDiffService since you dupicated this in two places

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Much nicer!

@ToddGrun ToddGrun merged commit 0cc8e4f into dotnet:main Jun 26, 2024
25 checks passed
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Jun 26, 2024
@RikkiGibson RikkiGibson modified the milestones: Next, 17.12 P1 Jul 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.

3 participants