BIDeveloperExtensions / bideveloperextensions

A Visual Studio extension that enhances development functionality in Business Intelligence Development Studio (BIDS) and SQL Server Data Tools (SSDT).
https://bideveloperextensions.github.io
Other
87 stars 24 forks source link

BI Developer Extensions hanging Visual Studio while walking installed extensions on UI thread #130

Open davkean opened 2 years ago

davkean commented 2 years ago

Describe the bug I'm from the Visual Studio performance team and our telemetry is showing us that BI Developer Extensions extension is causing Visual Studio responsiveness issues by walking all installed extensions while on the UI thread. This has caused Visual Studio to freeze the following amounts over the past 21 days:

Blame Expressed Hits Total Hits Duration (75th Percentile) Delayed Mouse Clicks Delayed Key Strokes
bidshelper2019.dll!BIDSHelper.BIDSHelperPackage.OriginalInitialize 132 892 5.10 sec 126 7

Expressed delays are situations where the UI hung while within this method and it interrupted/prevented users mouse or keyboard input. Total hits are all the times the UI hung while within this method, regardless of whether input was interrupted.

The lines of code in question are these:

https://github.com/BIDeveloperExtensions/bideveloperextensions/blob/master/BidsHelperPackage.cs#L165-L208

Version/To Reproduce This data comes our telemetry system, so we do not have any information on the versions of BI Developer Extensions or any dlls involved in this problem. We also have no understanding of the steps involved to reproduce the above situation other than the fact this data was just captured from real world usage.

Expected behavior This code should avoid performing this operation on the UI thread. IVsExtensionManager is free-threaded and can be accessed on a background thread, move the SwitchToMainThreadAsync to after it, or introduce a new method that does something like this:


private async Task WalkExtensionsAsync()
{
    await TaskScheduler.Default;

    var em = await  GetServiceAsync<SVsExtensionManager, IVsExtensionManager>(); // NOTE the use of GetServiceAsync, not GetService

    foreach (Microsoft.VisualStudio.ExtensionManager.IInstalledExtension i in em.GetInstalledExtensions())
    { 
      ...
    }
}