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

Throttle designer attribute processing. #67056

Merged
merged 12 commits into from
Feb 26, 2023

Conversation

CyrusNajmabadi
Copy link
Member

This service runs in the BG, so we don't want it saturating OOP with too much work. THere are a few major changes here.

  1. moved off of parallel work to serial, to not overwhelm the threadpool.
  2. added small delay between processing current active file, vs non-active file. it's important when a user makes an edit htat we update the designer attribute for that file right away. it's less likely/important to update the other files in that project (or other projects).
  3. moved construction of a project's compilation to After the check we make for it's semantic version. no point in computing compilations if the semantic version is the same and we're just going to skip all files in the project anyways.

@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner February 25, 2023 18:15
_documentToLastReportedInformation.TryGetValue(data.DocumentId, out var existingInfo);
if (existingInfo.category != data.Category)
results.Add(data);
if (data?.Category != existingInfo.category)
Copy link
Member Author

Choose a reason for hiding this comment

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

Suggested change
if (data?.Category != existingInfo.category)
if (data.Value.Category != existingInfo.category)

var designerCategoryType = compilation.DesignerCategoryAttributeType();
if (designerCategoryType == null)
return;
// Defer expensive work until it's actually needed.
Copy link
Member Author

Choose a reason for hiding this comment

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

made values lazy to defer until needed.

{
var compilation = await project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false);
return compilation.DesignerCategoryAttributeType() != null;
}, cacheResult: true));
Copy link
Member Author

Choose a reason for hiding this comment

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

figuring out if a set of references contains the DesignCategoryAttribute can be computed/cached for that set of references. As those rarely change for a project, it's much more efficient than having to continually use the project and create the compilation for it.

}

using var _2 = ArrayBuilder<DesignerAttributeData>.GetInstance(tasks.Count, out var results);
Copy link
Member Author

Choose a reason for hiding this comment

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

removed parallel processing here. this runs in the bg, and uses resources that active features (like lightbulbs) want to be using.

}

public static async Task<string?> ComputeDesignerAttributeCategoryAsync(
AsyncLazy<bool> lazyHasDesignerCategoryType, Document document, CancellationToken cancellationToken)
Copy link
Member Author

Choose a reason for hiding this comment

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

helper was in a sibling file. just inlined into this.

if (designerCategoryType == null)
return;
// Defer expensive work until it's actually needed.
var lazyProjectVersion = AsyncLazy.Create(project.GetSemanticVersionAsync, cacheResult: true);
Copy link
Contributor

Choose a reason for hiding this comment

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

The original code invoked GetDependentSemanticVersionAsync. Is the change to GetSemanticVersionAsync intentional here?

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. will add comment.

CancellationToken cancellationToken)
{
using var _1 = ArrayBuilder<Task<DesignerAttributeData?>>.GetInstance(out var tasks);
using var _ = ArrayBuilder<(DesignerAttributeData data, VersionStamp version)>.GetInstance(out var results);
foreach (var document in project.Documents)
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably add a comment here why we prefer to process documents sequentially instead of concurrently?

Copy link
Member Author

Choose a reason for hiding this comment

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

sure. will do.

Copy link
Contributor

@mavasani mavasani left a comment

Choose a reason for hiding this comment

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

LGTM. I'll validate the performance numbers on top of this PR. Thanks!

@CyrusNajmabadi CyrusNajmabadi merged commit 4641f2b into dotnet:main Feb 26, 2023
@ghost ghost added this to the Next milestone Feb 26, 2023
@CyrusNajmabadi CyrusNajmabadi deleted the designerAttributeWork branch March 1, 2023 23:49
@RikkiGibson RikkiGibson modified the milestones: Next, 17.6 P2 Mar 2, 2023
@mavasani mavasani added the Performance-Scenario-Diagnostics This issue affects diagnostics computation performance for lightbulb, background analysis, tagger. label May 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Performance-Scenario-Diagnostics This issue affects diagnostics computation performance for lightbulb, background analysis, tagger.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants