Skip to content

Speed up VisualStudioProject construction#60351

Merged
jasonmalinowski merged 2 commits intodotnet:mainfrom
jasonmalinowski:speed-up-visualstudioproject-construction
Mar 28, 2022
Merged

Speed up VisualStudioProject construction#60351
jasonmalinowski merged 2 commits intodotnet:mainfrom
jasonmalinowski:speed-up-visualstudioproject-construction

Conversation

@jasonmalinowski
Copy link
Copy Markdown
Member

Closes #55297

Loading these services during the VisualStudioProject constructor
means they're being loaded during the initial project creation which
is earlier than they're needed and can hold up other work. Let's not
ask for them until we actually need them.
@jasonmalinowski jasonmalinowski requested a review from a team as a code owner March 23, 2022 23:05
@jasonmalinowski jasonmalinowski self-assigned this Mar 23, 2022
@ghost ghost added the Area-IDE label Mar 23, 2022
@jasonmalinowski jasonmalinowski force-pushed the speed-up-visualstudioproject-construction branch from 6f978e9 to b8a6063 Compare March 23, 2022 23:30
@dotnet dotnet deleted a comment from azure-pipelines bot Mar 25, 2022
@dotnet dotnet deleted a comment from azure-pipelines bot Mar 25, 2022
@jasonmalinowski jasonmalinowski force-pushed the speed-up-visualstudioproject-construction branch from b8a6063 to e05579f Compare March 25, 2022 00:13
// task is completed, we know that the WaitUntilFullyLoadedAsync call will have actually finished and we're
// fully loaded.
var isFullyLoadedTask = workspaceStatusService?.IsFullyLoadedAsync(CancellationToken.None);
var isFullyLoaded = isFullyLoadedTask is { IsCompleted: true } && isFullyLoadedTask.GetAwaiter().GetResult();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

does this .IsCompleted check actually work well? i'm worried that some part of the IsFullyLaodedAsync call is actually async (Even trivially), and we just get a task back that this is always false for.

i think i woudl like it if IsFullyLaodedAsync actually guaranteed the behavior you're looking for here by having a single task that it creates and caches and then returns to all future callers. since i think we can only fully load once... that seems viable.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@CyrusNajmabadi I agree the pattern isn't good, it's not new here. @sharwell might recall if we actually know if this works?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Original conversation where this pattern was discussed: #48215 (comment)

There is probably a question as to whether we need to maintain the telemetry here at all, given everything that has gone on since Paul originally requested it.

// After the call to EnsureDocumentOptionProvidersInitializedAsync, everything can be off the UI thread.
// Thus, we have a ConfigureAwait(false) on the call and switch explicitly after.
await _visualStudioWorkspaceImpl.EnsureDocumentOptionProvidersInitializedAsync(cancellationToken).ConfigureAwait(false);
await TaskScheduler.Default;
Copy link
Copy Markdown
Contributor

@Therzok Therzok Mar 25, 2022

Choose a reason for hiding this comment

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

Don't ConfigureAwait(false) and await TaskScheduler.Default do the same thing?

It's possible await TaskScheduler.Default is already completed so it runs synchronously, but seems redundant, maybe I'm missing something?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@Therzok: the .ConfigureAwait(false) only matters if the EnsureDocumentOptionProvidersInitializedAsync actually yields; if it completes synchronously we'd stay on the UI thread.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Which to clarify: that means we need the await TaskScheduler.Default; but as @sharwell pointed out we don't want to have the first await come to the UI thread only to immediately bounce to the UI thread, so we kinda end up with this (admittedly odd) pattern.

Copy link
Copy Markdown
Contributor

@Therzok Therzok Mar 25, 2022

Choose a reason for hiding this comment

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

That is very good to know, thank you! System.Threading.Task makes me doubt I know anything.

@jasonmalinowski jasonmalinowski merged commit 38885db into dotnet:main Mar 28, 2022
@ghost ghost added this to the Next milestone Mar 28, 2022
@jasonmalinowski jasonmalinowski deleted the speed-up-visualstudioproject-construction branch March 28, 2022 18:45
@allisonchou allisonchou modified the milestones: Next, 17.2.P3 Mar 28, 2022
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.

[Responsiveness] Roslyn initialization is forced onto the UI thread, forcing the project system to synchronize initialize it (6.9% of solution open)

6 participants