Skip to content

Commit 722bbed

Browse files
majochapsfinaki
andauthored
AsyncLocal diagnostics, clean slate (#16779)
* fix some inconsistencies * we don't intend to dispose this ever * removed * multiple loggers * fix RegisterAndImportReferencedAssemblies * fix deadlock in fsi * fix some BuildGraphTests * restore asyncmemoize * fix missing logger in test * format * fix transparent compiler nre * cleanup * default value * add some comments * foramt and notes to make it green if it's green * wrap any parallel computations that potentially push diagnostics * try to fix buildgraphtests * try to eradicate deadlocks in tests * fix buildgraph test * disable for a moment * flatten exceptions * reshuffle * prevent graphnode deadlock * yield * diff * add some comments * add AsyncLocal test * more testing * not needed after all? * test * format * revert * try RunContinuationsAsynchronously * try to deal with deadlock another way * nope * revert * format * restore release notes * add test for ListParallel * speed up test * improve test * simpler MultipleDiagnosticsLoggers * rename and speedup test * parallel logging perf * remove SwitchToThreadPool * sequential * Revert "sequential" This reverts commit 8c77c0c. * revert spurious change * fix comments * test MultipleDiagnosticsLoggers * add comment and clean up --------- Co-authored-by: Petr <[email protected]>
1 parent 5a6f8b7 commit 722bbed

File tree

26 files changed

+696
-740
lines changed

26 files changed

+696
-740
lines changed

docs/release-notes/.FSharp.Compiler.Service/8.0.400.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@
2222

2323
* Minor compiler perf improvements. ([PR #17130](https://github.com/dotnet/fsharp/pull/17130))
2424
* Improve error of Active Pattern case Argument Count Not Match ([PR #16846](https://github.com/dotnet/fsharp/pull/16846))
25-
* Reduce allocations in compiler checking via `ValueOption` usage ([PR #16822](https://github.com/dotnet/fsharp/pull/16822))
25+
* AsyncLocal diagnostics context. ([PR #16779](https://github.com/dotnet/fsharp/pull/16779))
26+
* Reduce allocations in compiler checking via `ValueOption` usage ([PR #16822](https://github.com/dotnet/fsharp/pull/16822))
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
### Fixed
22

33
* Make tooltips work in file with no solution. ([PR #17054](https://github.com/dotnet/fsharp/pull/17054))
4+
5+
### Changed
6+
7+
* Use AsyncLocal diagnostics context. ([PR #16779])(https://github.com/dotnet/fsharp/pull/16779))

src/Compiler/Driver/CompilerConfig.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ and IProjectReference =
252252
abstract FileName: string
253253

254254
/// Evaluate raw contents of the assembly file generated by the project
255-
abstract EvaluateRawContents: unit -> NodeCode<ProjectAssemblyDataResult>
255+
abstract EvaluateRawContents: unit -> Async<ProjectAssemblyDataResult>
256256

257257
/// Get the logical timestamp that would be the timestamp of the assembly file generated by the project
258258
///

src/Compiler/Driver/CompilerConfig.fsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ and IProjectReference =
8686
/// Evaluate raw contents of the assembly file generated by the project.
8787
/// 'None' may be returned if an in-memory view of the contents is, for some reason,
8888
/// not available. In this case the on-disk view of the contents will be preferred.
89-
abstract EvaluateRawContents: unit -> NodeCode<ProjectAssemblyDataResult>
89+
abstract EvaluateRawContents: unit -> Async<ProjectAssemblyDataResult>
9090

9191
/// Get the logical timestamp that would be the timestamp of the assembly file generated by the project.
9292
///

src/Compiler/Driver/CompilerImports.fs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2159,14 +2159,14 @@ and [<Sealed>] TcImports
21592159
(
21602160
ctok,
21612161
r: AssemblyResolution
2162-
) : NodeCode<(_ * (unit -> AvailableImportedAssembly list)) option> =
2163-
node {
2162+
) : Async<(_ * (unit -> AvailableImportedAssembly list)) option> =
2163+
async {
21642164
CheckDisposed()
21652165
let m = r.originalReference.Range
21662166
let fileName = r.resolvedPath
21672167

21682168
let! contentsOpt =
2169-
node {
2169+
async {
21702170
match r.ProjectReference with
21712171
| Some ilb -> return! ilb.EvaluateRawContents()
21722172
| None -> return ProjectAssemblyDataResult.Unavailable true
@@ -2229,21 +2229,23 @@ and [<Sealed>] TcImports
22292229

22302230
// NOTE: When used in the Language Service this can cause the transitive checking of projects. Hence it must be cancellable.
22312231
member tcImports.RegisterAndImportReferencedAssemblies(ctok, nms: AssemblyResolution list) =
2232-
node {
2232+
async {
22332233
CheckDisposed()
22342234

2235+
22352236
let tcConfig = tcConfigP.Get ctok
22362237

22372238
let runMethod =
22382239
match tcConfig.parallelReferenceResolution with
2239-
| ParallelReferenceResolution.On -> NodeCode.Parallel
2240-
| ParallelReferenceResolution.Off -> NodeCode.Sequential
2240+
| ParallelReferenceResolution.On -> MultipleDiagnosticsLoggers.Parallel
2241+
| ParallelReferenceResolution.Off -> MultipleDiagnosticsLoggers.Sequential
22412242

22422243
let! results =
22432244
nms
22442245
|> List.map (fun nm ->
2245-
node {
2246+
async {
22462247
try
2248+
use _ = new CompilationGlobalsScope()
22472249
return! tcImports.TryRegisterAndPrepareToImportReferencedDll(ctok, nm)
22482250
with e ->
22492251
errorR (Error(FSComp.SR.buildProblemReadingAssembly (nm.resolvedPath, e.Message), nm.originalReference.Range))
@@ -2283,7 +2285,7 @@ and [<Sealed>] TcImports
22832285
ReportWarnings warns
22842286

22852287
tcImports.RegisterAndImportReferencedAssemblies(ctok, res)
2286-
|> NodeCode.RunImmediateWithoutCancellation
2288+
|> Async.RunImmediate
22872289
|> ignore
22882290

22892291
true
@@ -2377,7 +2379,7 @@ and [<Sealed>] TcImports
23772379
// we dispose TcImports is because we need to dispose type providers, and type providers are never included in the framework DLL set.
23782380
// If a framework set ever includes type providers, you will not have to worry about explicitly calling Dispose as the Finalizer will handle it.
23792381
static member BuildFrameworkTcImports(tcConfigP: TcConfigProvider, frameworkDLLs, nonFrameworkDLLs) =
2380-
node {
2382+
async {
23812383
let ctok = CompilationThreadToken()
23822384
let tcConfig = tcConfigP.Get ctok
23832385

@@ -2454,7 +2456,7 @@ and [<Sealed>] TcImports
24542456
resolvedAssemblies |> List.choose tryFindEquivPrimaryAssembly
24552457

24562458
let! fslibCcu, fsharpCoreAssemblyScopeRef =
2457-
node {
2459+
async {
24582460
if tcConfig.compilingFSharpCore then
24592461
// When compiling FSharp.Core.dll, the fslibCcu reference to FSharp.Core.dll is a delayed ccu thunk fixed up during type checking
24602462
return CcuThunk.CreateDelayed getFSharpCoreLibraryName, ILScopeRef.Local
@@ -2548,7 +2550,7 @@ and [<Sealed>] TcImports
25482550
dependencyProvider
25492551
) =
25502552

2551-
node {
2553+
async {
25522554
let ctok = CompilationThreadToken()
25532555
let tcConfig = tcConfigP.Get ctok
25542556

@@ -2566,7 +2568,7 @@ and [<Sealed>] TcImports
25662568
}
25672569

25682570
static member BuildTcImports(tcConfigP: TcConfigProvider, dependencyProvider) =
2569-
node {
2571+
async {
25702572
let ctok = CompilationThreadToken()
25712573
let tcConfig = tcConfigP.Get ctok
25722574

@@ -2598,7 +2600,7 @@ let RequireReferences (ctok, tcImports: TcImports, tcEnv, thisAssemblyName, reso
25982600

25992601
let ccuinfos =
26002602
tcImports.RegisterAndImportReferencedAssemblies(ctok, resolutions)
2601-
|> NodeCode.RunImmediateWithoutCancellation
2603+
|> Async.RunImmediate
26022604

26032605
let asms =
26042606
ccuinfos

src/Compiler/Driver/CompilerImports.fsi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,14 @@ type TcImports =
199199
member internal Base: TcImports option
200200

201201
static member BuildFrameworkTcImports:
202-
TcConfigProvider * AssemblyResolution list * AssemblyResolution list -> NodeCode<TcGlobals * TcImports>
202+
TcConfigProvider * AssemblyResolution list * AssemblyResolution list -> Async<TcGlobals * TcImports>
203203

204204
static member BuildNonFrameworkTcImports:
205205
TcConfigProvider * TcImports * AssemblyResolution list * UnresolvedAssemblyReference list * DependencyProvider ->
206-
NodeCode<TcImports>
206+
Async<TcImports>
207207

208208
static member BuildTcImports:
209-
tcConfigP: TcConfigProvider * dependencyProvider: DependencyProvider -> NodeCode<TcGlobals * TcImports>
209+
tcConfigP: TcConfigProvider * dependencyProvider: DependencyProvider -> Async<TcGlobals * TcImports>
210210

211211
/// Process a group of #r in F# Interactive.
212212
/// Adds the reference to the tcImports and add the ccu to the type checking environment.

src/Compiler/Driver/fsc.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ let main1
615615
// Import basic assemblies
616616
let tcGlobals, frameworkTcImports =
617617
TcImports.BuildFrameworkTcImports(foundationalTcConfigP, sysRes, otherRes)
618-
|> NodeCode.RunImmediateWithoutCancellation
618+
|> Async.RunImmediate
619619

620620
let ilSourceDocs =
621621
[
@@ -664,7 +664,7 @@ let main1
664664

665665
let tcImports =
666666
TcImports.BuildNonFrameworkTcImports(tcConfigP, frameworkTcImports, otherRes, knownUnresolved, dependencyProvider)
667-
|> NodeCode.RunImmediateWithoutCancellation
667+
|> Async.RunImmediate
668668

669669
// register tcImports to be disposed in future
670670
disposables.Register tcImports

src/Compiler/Facilities/AsyncMemoize.fs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ type internal MemoizeReply<'TValue> =
5151
| New of CancellationToken
5252
| Existing of Task<'TValue>
5353

54-
type internal MemoizeRequest<'TValue> = GetOrCompute of NodeCode<'TValue> * CancellationToken
54+
type internal MemoizeRequest<'TValue> = GetOrCompute of Async<'TValue> * CancellationToken
5555

5656
[<DebuggerDisplay("{DebuggerDisplay}")>]
5757
type internal Job<'TValue> =
58-
| Running of TaskCompletionSource<'TValue> * CancellationTokenSource * NodeCode<'TValue> * DateTime * ResizeArray<DiagnosticsLogger>
58+
| Running of TaskCompletionSource<'TValue> * CancellationTokenSource * Async<'TValue> * DateTime * ResizeArray<DiagnosticsLogger>
5959
| Completed of 'TValue * (PhasedDiagnostic * FSharpDiagnosticSeverity) list
6060
| Canceled of DateTime
6161
| Failed of DateTime * exn // TODO: probably we don't need to keep this
@@ -286,7 +286,13 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
286286
key.Key,
287287
key.Version,
288288
key.Label,
289-
(Running(TaskCompletionSource(), cts, computation, DateTime.Now, ResizeArray()))
289+
(Running(
290+
TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously),
291+
cts,
292+
computation,
293+
DateTime.Now,
294+
ResizeArray()
295+
))
290296
)
291297

292298
otherVersions
@@ -314,7 +320,7 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
314320

315321
let processStateUpdate post (key: KeyData<_, _>, action: StateUpdate<_>) =
316322
task {
317-
do! Task.Delay 0
323+
do! Task.Yield()
318324

319325
do!
320326
lock.Do(fun () ->
@@ -359,7 +365,7 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
359365
DiagnosticsThreadStatics.DiagnosticsLogger <- cachingLogger
360366

361367
try
362-
let! result = computation |> Async.AwaitNodeCode
368+
let! result = computation
363369
post (key, (JobCompleted(result, cachingLogger.CapturedDiagnostics)))
364370
return ()
365371
finally
@@ -482,14 +488,14 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
482488
Version = key.GetVersion()
483489
}
484490

485-
node {
486-
let! ct = NodeCode.CancellationToken
491+
async {
492+
let! ct = Async.CancellationToken
487493

488494
let callerDiagnosticLogger = DiagnosticsThreadStatics.DiagnosticsLogger
489495

490496
match!
491497
processRequest post (key, GetOrCompute(computation, ct)) callerDiagnosticLogger
492-
|> NodeCode.AwaitTask
498+
|> Async.AwaitTask
493499
with
494500
| New internalCt ->
495501

@@ -507,15 +513,15 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
507513
log (Started, key)
508514

509515
try
510-
let! result = computation |> Async.AwaitNodeCode
516+
let! result = computation
511517
post (key, (JobCompleted(result, cachingLogger.CapturedDiagnostics)))
512518
return result
513519
finally
514520
DiagnosticsThreadStatics.DiagnosticsLogger <- currentLogger
515521
},
516522
cancellationToken = linkedCtSource.Token
517523
)
518-
|> NodeCode.AwaitTask
524+
|> Async.AwaitTask
519525
with
520526
| TaskCancelled ex ->
521527
// TODO: do we need to do anything else here? Presumably it should be done by the registration on
@@ -531,7 +537,7 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
531537
post (key, (JobFailed(ex, cachingLogger.CapturedDiagnostics)))
532538
return raise ex
533539

534-
| Existing job -> return! job |> NodeCode.AwaitTask
540+
| Existing job -> return! job |> Async.AwaitTask
535541

536542
}
537543

src/Compiler/Facilities/AsyncMemoize.fsi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ type internal AsyncMemoize<'TKey, 'TVersion, 'TValue when 'TKey: equality and 'T
6666

6767
member Clear: predicate: ('TKey -> bool) -> unit
6868

69-
member Get: key: ICacheKey<'TKey, 'TVersion> * computation: NodeCode<'TValue> -> NodeCode<'TValue>
69+
member Get: key: ICacheKey<'TKey, 'TVersion> * computation: Async<'TValue> -> Async<'TValue>
7070

71-
member Get': key: 'TKey * computation: NodeCode<'TValue> -> NodeCode<'TValue>
71+
member Get': key: 'TKey * computation: Async<'TValue> -> Async<'TValue>
7272

7373
member TryGet: key: 'TKey * predicate: ('TVersion -> bool) -> 'TValue option
7474

0 commit comments

Comments
 (0)