Skip to content

Commit 1550bf4

Browse files
authored
Transparent compiler buffs (#1356)
* Set cache sizes for TC * Ensure typechecks are accurate on hover/codelens * Add RunContinuationsAsynchronously to TCS * cleanup ITextDocumentIdentifier * Add analyzers thorttle * Add typecheck throttler
1 parent b6bfc04 commit 1550bf4

File tree

9 files changed

+65
-28
lines changed

9 files changed

+65
-28
lines changed

src/FsAutoComplete.Core/AdaptiveExtensions.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ and AdaptiveCancellableTask<'a>(cancel: unit -> unit, real: Task<'a>) =
408408
if real.IsCompleted then
409409
real
410410
else
411-
cachedTcs <- new TaskCompletionSource<'a>()
411+
cachedTcs <- new TaskCompletionSource<'a>(TaskCreationOptions.RunContinuationsAsynchronously)
412412

413413
cachedTcs.TrySetFromTaskFinished real
414414

src/FsAutoComplete.Core/CompilerServiceInterface.fs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,22 @@ type CompilerProjectOption =
7878
| BackgroundCompiler(options) -> options.OtherOptions |> Array.toList
7979
| TransparentCompiler(snapshot) -> snapshot.OtherOptions
8080

81-
type FSharpCompilerServiceChecker(hasAnalyzers, typecheckCacheSize, parallelReferenceResolution, useTransparentCompiler)
82-
=
81+
type FSharpCompilerServiceChecker
82+
(
83+
hasAnalyzers,
84+
typecheckCacheSize,
85+
parallelReferenceResolution,
86+
useTransparentCompiler,
87+
?transparentCompilerCacheSizes: int
88+
) =
8389
let checker =
90+
let cacheSize =
91+
if useTransparentCompiler then
92+
TransparentCompiler.CacheSizes.Create(defaultArg transparentCompilerCacheSizes 10)
93+
|> Some
94+
else
95+
None
96+
8497
FSharpChecker.Create(
8598
projectCacheSize = 200,
8699
keepAssemblyContents = hasAnalyzers,
@@ -91,7 +104,8 @@ type FSharpCompilerServiceChecker(hasAnalyzers, typecheckCacheSize, parallelRefe
91104
enablePartialTypeChecking = not hasAnalyzers,
92105
parallelReferenceResolution = parallelReferenceResolution,
93106
captureIdentifiersWhenParsing = true,
94-
useTransparentCompiler = useTransparentCompiler
107+
useTransparentCompiler = useTransparentCompiler,
108+
?transparentCompilerCacheSizes = cacheSize
95109
)
96110

97111
let entityCache = EntityCache()
@@ -502,7 +516,10 @@ type FSharpCompilerServiceChecker(hasAnalyzers, typecheckCacheSize, parallelRefe
502516
let ops =
503517
MemoryCacheEntryOptions().SetSize(1).SetSlidingExpiration(TimeSpan.FromMinutes(5.))
504518

505-
return lastCheckResults.Set(filePath, r, ops)
519+
lastCheckResults.Set(filePath, WeakReference<ParseAndCheckResults>(r), ops)
520+
|> ignore<WeakReference<ParseAndCheckResults>>
521+
522+
return r
506523
else
507524
return r
508525
with ex ->
@@ -553,7 +570,10 @@ type FSharpCompilerServiceChecker(hasAnalyzers, typecheckCacheSize, parallelRefe
553570
let ops =
554571
MemoryCacheEntryOptions().SetSize(1).SetSlidingExpiration(TimeSpan.FromMinutes(5.))
555572

556-
return lastCheckResults.Set(filePath, r, ops)
573+
lastCheckResults.Set(filePath, WeakReference<ParseAndCheckResults>(r), ops)
574+
|> ignore<WeakReference<ParseAndCheckResults>>
575+
576+
return r
557577
else
558578
return r
559579
with ex ->
@@ -578,8 +598,11 @@ type FSharpCompilerServiceChecker(hasAnalyzers, typecheckCacheSize, parallelRefe
578598

579599
checkerLogger.info (Log.setMessage "{opName}" >> Log.addContextDestructured "opName" opName)
580600

581-
match lastCheckResults.TryGetValue<ParseAndCheckResults>(file) with
582-
| (true, v) -> Some v
601+
match lastCheckResults.TryGetValue<WeakReference<ParseAndCheckResults>>(file) with
602+
| (true, v) ->
603+
match v.TryGetTarget() with
604+
| (true, v) -> Some v
605+
| _ -> None
583606
| _ -> None
584607

585608
member _.TryGetRecentCheckResultsForFile(file: string<LocalPath>, snapshot: FSharpProjectSnapshot) =

src/FsAutoComplete.Core/CompilerServiceInterface.fsi

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ type CompilerProjectOption =
2929

3030
type FSharpCompilerServiceChecker =
3131
new:
32-
hasAnalyzers: bool * typecheckCacheSize: int64 * parallelReferenceResolution: bool * useTransparentCompiler: bool ->
32+
hasAnalyzers: bool *
33+
typecheckCacheSize: int64 *
34+
parallelReferenceResolution: bool *
35+
useTransparentCompiler: bool *
36+
?transparentCompilerCacheSizes: int ->
3337
FSharpCompilerServiceChecker
3438

3539
member DisableInMemoryProjectReferences: bool with get, set

src/FsAutoComplete.Core/Utils.fs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ module ProcessHelper =
7070

7171
let WaitForExitAsync (p: Process) =
7272
asyncEx {
73-
let tcs = TaskCompletionSource<obj>()
73+
let tcs =
74+
TaskCompletionSource<obj>(TaskCreationOptions.RunContinuationsAsynchronously)
75+
7476
p.EnableRaisingEvents <- true
7577
p.Exited.Add(fun _args -> tcs.TrySetResult(null) |> ignore)
7678

src/FsAutoComplete/LspHelpers.fs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,7 @@ module Conversions =
8686
| Some(U2.C2 code) -> code |> Some
8787
| None -> None
8888

89-
type TextDocumentIdentifier with
90-
91-
member doc.GetFilePath() = Path.FileUriToLocalPath doc.Uri
92-
93-
type VersionedTextDocumentIdentifier with
89+
type ITextDocumentIdentifier with
9490

9591
member doc.GetFilePath() = Path.FileUriToLocalPath doc.Uri
9692

src/FsAutoComplete/LspHelpers.fsi

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,7 @@ module Conversions =
4646

4747
member CodeAsString: string option
4848

49-
type TextDocumentIdentifier with
50-
51-
member GetFilePath: unit -> string
52-
53-
type VersionedTextDocumentIdentifier with
49+
type ITextDocumentIdentifier with
5450

5551
member GetFilePath: unit -> string
5652

src/FsAutoComplete/LspServers/AdaptiveFSharpLspServer.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,7 @@ type AdaptiveFSharpLspServer
939939
let (filePath, pos) = getFilePathAndPosition p
940940
let! volatileFile = state.GetOpenFileOrRead filePath |> AsyncResult.ofStringErr
941941
let! lineStr = volatileFile.Source |> tryGetLineStr pos |> Result.lineLookupErr
942-
and! tyRes = state.GetOpenFileTypeCheckResultsCached filePath |> AsyncResult.ofStringErr
942+
and! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr
943943

944944
match tyRes.TryGetToolTipEnhanced pos lineStr with
945945
| Some tooltipResult ->
@@ -1580,7 +1580,7 @@ type AdaptiveFSharpLspServer
15801580
let filePath = Path.FileUriToLocalPath data.[0] |> Utils.normalizePath
15811581

15821582
try
1583-
let! tyRes = state.GetOpenFileTypeCheckResultsCached filePath |> AsyncResult.ofStringErr
1583+
let! tyRes = state.GetOpenFileTypeCheckResults filePath |> AsyncResult.ofStringErr
15841584

15851585

15861586
logger.info (

src/FsAutoComplete/LspServers/AdaptiveServerState.fs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,14 @@ type AdaptiveState
377377
disposables.Add
378378
<| fileParsed.Publish.Subscribe(fun (parseResults, proj, ct) -> detectTests parseResults proj ct)
379379

380+
let analyzersLocker = new SemaphoreSlim(1, 1)
381+
382+
let typecheckLocker =
383+
let maxConcurrency =
384+
Math.Max(1.0, Math.Floor(float System.Environment.ProcessorCount * 0.75)) |> int
385+
386+
new SemaphoreSlim(maxConcurrency, maxConcurrency)
387+
380388
let builtInCompilerAnalyzers config (file: VolatileFile) (tyRes: ParseAndCheckResults) =
381389
let filePath = file.FileName
382390
let filePathUntag = UMX.untag filePath
@@ -390,14 +398,15 @@ type AdaptiveState
390398
let checkUnusedOpens =
391399
asyncEx {
392400
try
401+
let! ct = Async.CancellationToken
402+
use! _l = analyzersLocker.LockAsync(ct)
393403
use progress = progressLookup.CreateProgressReport(lspClient, cancellable = true)
394404
do! progress.Begin($"Checking unused opens {fileName}...", message = filePathUntag)
395405

396406
let! unused =
397407
UnusedOpens.getUnusedOpens (tyRes.GetCheckResults, getSourceLine)
398408
|> Async.withCancellation progress.CancellationToken
399409

400-
let! ct = Async.CancellationToken
401410
notifications.Trigger(NotificationEvent.UnusedOpens(filePath, (unused |> List.toArray), file.Version), ct)
402411
with e ->
403412
logger.error (Log.setMessage "checkUnusedOpens failed" >> Log.addExn e)
@@ -406,6 +415,8 @@ type AdaptiveState
406415
let checkUnusedDeclarations =
407416
asyncEx {
408417
try
418+
let! ct = Async.CancellationToken
419+
use! _l = analyzersLocker.LockAsync(ct)
409420
use progress = progressLookup.CreateProgressReport(lspClient, cancellable = true)
410421
do! progress.Begin($"Checking unused declarations {fileName}...", message = filePathUntag)
411422

@@ -417,7 +428,6 @@ type AdaptiveState
417428

418429
let unused = unused |> Seq.toArray
419430

420-
let! ct = Async.CancellationToken
421431
notifications.Trigger(NotificationEvent.UnusedDeclarations(filePath, unused, file.Version), ct)
422432
with e ->
423433
logger.error (Log.setMessage "checkUnusedDeclarations failed" >> Log.addExn e)
@@ -426,6 +436,8 @@ type AdaptiveState
426436
let checkSimplifiedNames =
427437
asyncEx {
428438
try
439+
let! ct = Async.CancellationToken
440+
use! _l = analyzersLocker.LockAsync(ct)
429441
use progress = progressLookup.CreateProgressReport(lspClient, cancellable = true)
430442
do! progress.Begin($"Checking simplifying of names {fileName}...", message = filePathUntag)
431443

@@ -434,7 +446,6 @@ type AdaptiveState
434446
|> Async.withCancellation progress.CancellationToken
435447

436448
let simplified = Array.ofSeq simplified
437-
let! ct = Async.CancellationToken
438449
notifications.Trigger(NotificationEvent.SimplifyNames(filePath, simplified, file.Version), ct)
439450
with e ->
440451
logger.error (Log.setMessage "checkSimplifiedNames failed" >> Log.addExn e)
@@ -443,6 +454,8 @@ type AdaptiveState
443454
let checkUnnecessaryParentheses =
444455
asyncEx {
445456
try
457+
let! ct = Async.CancellationToken
458+
use! _l = analyzersLocker.LockAsync(ct)
446459
use progress = progressLookup.CreateProgressReport(lspClient)
447460
do! progress.Begin($"Checking for unnecessary parentheses {fileName}...", message = filePathUntag)
448461

@@ -464,8 +477,6 @@ type AdaptiveState
464477

465478
| _ -> ranges)
466479

467-
let! ct = Async.CancellationToken
468-
469480
notifications.Trigger(
470481
NotificationEvent.UnnecessaryParentheses(filePath, Array.ofSeq unnecessaryParentheses, file.Version),
471482
ct
@@ -1599,6 +1610,8 @@ type AdaptiveState
15991610

16001611
]
16011612

1613+
let! ct = Async.CancellationToken
1614+
use! _l = typecheckLocker.LockAsync ct
16021615
use _ = fsacActivitySource.StartActivityForType(thisType, tags = tags)
16031616

16041617

src/FsAutoComplete/LspServers/Common.fs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ module Async =
158158
asyncEx {
159159
let! ct2 = Async.CancellationToken
160160
use cts = CancellationTokenSource.CreateLinkedTokenSource(ct, ct2)
161-
let tcs = new TaskCompletionSource<'a>()
161+
162+
let tcs =
163+
new TaskCompletionSource<'a>(TaskCreationOptions.RunContinuationsAsynchronously)
164+
162165
use _reg = cts.Token.Register(fun () -> tcs.TrySetCanceled(cts.Token) |> ignore)
163166

164167
let a =

0 commit comments

Comments
 (0)