Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes/.VisualStudio/18.vNext.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

### Fixed

* Improve Find All References performance by throttling parallel typechecks. ([PR #20128](https://github.com/dotnet/fsharp/pull/20128))
* Fixed Rename incorrectly renaming `get` and `set` keywords for properties with explicit accessors. ([Issue #18270](https://github.com/dotnet/fsharp/issues/18270), [PR #19252](https://github.com/dotnet/fsharp/pull/19252))
* Fixed Find All References crash when F# project contains non-F# files like `.cshtml`. ([Issue #16394](https://github.com/dotnet/fsharp/issues/16394), [PR #19252](https://github.com/dotnet/fsharp/pull/19252))
* Find All References for external DLL symbols now only searches projects that reference the specific assembly. ([Issue #10227](https://github.com/dotnet/fsharp/issues/10227), [PR #19252](https://github.com/dotnet/fsharp/pull/19252))
Expand Down
32 changes: 32 additions & 0 deletions vsintegration/src/FSharp.Editor/Common/CancellableTasks.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,38 @@ module CancellableTasks =
return! Task.WhenAll (tasks)
}

/// Runs the given tasks concurrently, but caps concurrent work to maxDegreeOfParallelism.
let inline whenAllThrottled maxDegreeOfParallelism (tasks: CancellableTask<'a> seq) =
cancellableTask {
let! ct = getCancellationToken ()
let semaphore = new SemaphoreSlim(maxDegreeOfParallelism: int)

let started =
[|
for task in tasks do
backgroundTask {
do! semaphore.WaitAsync(ct)

try
return! start ct task
finally
semaphore.Release() |> ignore
}
|]

let allTask = Task.WhenAll started

allTask.ContinueWith(
(fun (_: Task<'a[]>) -> semaphore.Dispose()),
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default
)
|> ignore

return! allTask
}

let inline whenAllTasks (tasks: CancellableTask seq) =
cancellableTask {
let! ct = getCancellationToken ()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[<AutoOpen>]
[<AutoOpen>]
module internal Microsoft.VisualStudio.FSharp.Editor.WorkspaceExtensions

open System
Expand Down Expand Up @@ -703,7 +703,8 @@ type Project with
documents
|> Seq.map (fun doc ->
doc.FindFSharpReferencesAsync(symbol, projectSnapshot, (fun range -> onFound doc range), userOpName))
|> CancellableTask.whenAll
// Throttle to avoid launching a typecheck per document in the project all at once.
|> CancellableTask.whenAllThrottled (max 1 Environment.ProcessorCount)
else
for doc in documents do
do! doc.FindFSharpReferencesAsync(symbol, projectSnapshot, (onFound doc), userOpName)
Expand Down
Loading