From f7d828756f50ddb63da073252efce52f3ce0d021 Mon Sep 17 00:00:00 2001 From: Todd Grunke Date: Mon, 24 Mar 2025 16:57:18 -0700 Subject: [PATCH] Do not call JTF.Run from a bg thread in options initialization Jan reported a speedometer regression in Threads_AdjustedBackgroundJTFRunCount_devenv when trying to merge the next version roslyn branch into VS. This codepath has changed significantly due to the package initialization changes I've been making. Specifically, RoslynPackage used to fire and forget a call to LoadOptionPersistersAsync in package initialization and now doesn't do this until after the package is loaded. Previously, after firing off this work, there would be a good amount of time before the first option was used, likely from ColorSchemaSettings.MigrateToColorSchemeSetting. Thus, the first call to GlobalOptions.GetOptionPersistersSlow would likely not have any async work remaining. My hypothesis is that even though a JTF.Run would have previously been invoked on a bg thread, it wouldn't have been reported as the task would have already been completed. LoadOptionPersistersAsync was intentionally moved to after the package load, and thus it's intentional that we don't frontload this work. It's now expected that when the first option is requested, that there is still async work remaining. The change in this PR makes it so if we are on a bg thread, we don't call JTF.Run in this context, instead just get the result directly. Blocking a bg thread while the options persisters finish loading isn't too concerning. Insertion PR reporting regression: https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequest/621620 --- src/Workspaces/Core/Portable/Options/GlobalOptionService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Workspaces/Core/Portable/Options/GlobalOptionService.cs b/src/Workspaces/Core/Portable/Options/GlobalOptionService.cs index 4418710c0c9a0..465af3bc1ea81 100644 --- a/src/Workspaces/Core/Portable/Options/GlobalOptionService.cs +++ b/src/Workspaces/Core/Portable/Options/GlobalOptionService.cs @@ -58,8 +58,9 @@ static ImmutableArray GetOptionPersistersSlow( ImmutableArray> persisterProviders, CancellationToken cancellationToken) { - if (workspaceThreadingService is not null) + if (workspaceThreadingService is not null && workspaceThreadingService.IsOnMainThread) { + // speedometer tests report jtf.run calls from background threads, so we try to avoid those. return workspaceThreadingService.Run(() => GetOptionPersistersAsync(persisterProviders, cancellationToken)); } else