Perf: `.Result` blocks `MailboxProcessor` thread in `FSharpProjectOptionsManager`
- Dominant language
- F#
- Stars
- 4.3k
- Forks
- 876
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 131
Description
## Description
`FSharpProjectOptionsManager.fs`'s `hasDependentVersionChanged` used blocking `.Result` calls on `GetDependentVersionAsync(ct).Result` when comparing non-F# project references. Since this function is invoked from `isProjectInvalidated`, which is called from `tryComputeOptions` / `tryComputeOptionsBySingleScriptOrFile` inside the `FSharpProjectOptionsReactor`'s `MailboxProcessor` loop, these synchronous waits could block the single-threaded reactor loop during project invalidation, causing UI/background responsiveness issues.
## Repro / Evidence
Identified via CPU profiling of background F# editor activity in Visual Studio; located via code search for `.Result` usages in `vsintegration/src/FSharp.Editor`.
## Fix
Convert `hasDependentVersionChanged` and `isProjectInvalidated` to `cancellableTask` workflows using `let!` instead of `.Result`, so the invalidation path is fully async and no longer blocks the mailbox loop.
## Priority
P2 (medium-term)
Contributor guide
Research direction
Start in vsintegration/src/FSharp.Editor/FSharpProjectOptionsManager.fs, focusing on hasDependentVersionChanged and isProjectInvalidated, then trace their calls from tryComputeOptions and tryComputeOptionsBySingleScriptOrFile in the FSharpProjectOptionsReactor MailboxProcessor loop. Replace the blocking dependent-version waits with cancellableTask workflows and verify that the invalidation path remains fully asynchronous without blocking the mailbox loop.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fsharp
- Domain
- developer-experience, performance, tooling
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100