-
Notifications
You must be signed in to change notification settings - Fork 803
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incremental builder with async lazy evaluation / Reactor removal #11573
Conversation
…naming from code review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Notes from deep review and co-working with @TIHan
src/fsharp/BuildGraph.fs
Outdated
static member AwaitTask(task: Task) = | ||
Node(wrapThreadStaticInfo(Async.AwaitTask task)) | ||
|
||
static member AwaitWaitHandle(waitHandle: WaitHandle) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only for test purposes - label it as such or rename to AwaitWaitHandleForTesting
src/fsharp/BuildGraph.fsi
Outdated
|
||
static member RunImmediate : computation: NodeCode<'T> * ?ct: CancellationToken -> 'T | ||
|
||
static member StartAsTask : computation: NodeCode<'T> * ?ct: CancellationToken -> Task<'T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename to StartAsTask_ForTesting
src/fsharp/BuildGraph.fsi
Outdated
[<AbstractClass;Sealed>] | ||
type NodeCode = | ||
|
||
static member RunImmediate : computation: NodeCode<'T> * ?ct: CancellationToken -> 'T |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At each callsite ct is None.
My preference: remove the cancellation token argument and rename to RunImmediateWithoutCancellation
Certainly make the ct argument non-optional as it's relaly important to know where we have non-cancellable code
src/fsharp/BuildGraph.fsi
Outdated
|
||
static member Sequential : computations: NodeCode<'T> seq -> NodeCode<'T []> | ||
|
||
static member AwaitWaitHandle : waitHandle: WaitHandle -> NodeCode<bool> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename to AwaitWaitHandle_ForTesting
src/fsharp/BuildGraph.fsi
Outdated
|
||
member GetValue: unit -> NodeCode<'T> | ||
|
||
member TryGetValue: unit -> 'T voption |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename to TryPeekValue
, since no compute is done
src/fsharp/BuildGraph.fsi
Outdated
/// By default, 'retryCompute' is 'true'. | ||
new : computation: NodeCode<'T> -> GraphNode<'T> | ||
|
||
member GetValue: unit -> NodeCode<'T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe make the computational aspect of this clearer in the name, e.g. ComputeValue
or GetOrComputeValue
src/fsharp/CompilerImports.fs
Outdated
RequireCompilationThread ctok // we don't want to do assembly resolution concurrently, we assume MSBuild doesn't handle this | ||
TcConfig.TryResolveLibsUsingMSBuildRules (tcConfig, assemblyList, rangeStartup, ResolveAssemblyReferenceMode.ReportErrors) | ||
// we don't want to do assembly resolution concurrently, we assume MSBuild doesn't handle this | ||
lock assemblyResolutionGate (fun () -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here the ultimate need for a lock is the call to tcConfig.legacyReferenceResolver.Impl.Resolve
See comment above. Agreed this looks like a reasonable place to acquire AssemblyResolutionLockToken
|
||
static member BuildFrameworkTcImports (tcConfigP: TcConfigProvider, frameworkDLLs, nonFrameworkDLLs) = | ||
node { | ||
let ctok = CompilationThreadToken() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change to AssumeCompilationThreadWithoutEvidence()
src/fsharp/service/service.fsi
Outdated
@@ -257,7 +257,7 @@ type public FSharpChecker = | |||
/// <param name="filename">The filename for the file.</param> | |||
/// <param name="options">The options for the project or script, used to determine active --define conditionals and other options relevant to parsing.</param> | |||
/// <param name="userOpName">An optional string used for tracing compiler operations associated with this request.</param> | |||
member GetBackgroundCheckResultsForFileInProject: filename: string * options: FSharpProjectOptions * ?userOpName: string -> Async<FSharpParseFileResults * FSharpCheckFileResults> | |||
member GetBackgroundCheckResultsForFileInProject: filename: string * options: FSharpProjectOptions * ?userOpName: string -> Async<(FSharpParseFileResults * FSharpCheckFileResults) option> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed this - no need to catch OperationCanceledException, no need to return options
Great, it passes. :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, I did a careful third online review with @TIHan and we added documentation and made some fixes. There are things to be done as follow up
-
Using the "save" trigger for scripts is not enough - we should request possible reanalysis each time the script comes into focus, otherwise red-squigglies will not be cleared after background file changes unless the user actually edits and saves. Have sent a repro to Will, he'll do this separately
-
When it's in main we can do InlineIfLambda on the 'Cancellable' methods like 'bind'
-
Check some FCS callstacks in the debugger (post hoc is ok)
-
Document the API changes in the FCS release notes, particularly the removal of the background build
…net#11573) * Adding AsyncLazy * Trying to get rid of cancellable and eventually use in incrementalbuilder * remove a lot of use of eventually and cancellable in incremental build * trying * More refactoring * drastrically less use of ctok * fixing build * Using reactor for foreground checking * more cleanup * more cleanup * Properly set a background build * fixing build * fixing build * trying to fix it * Added Seq.foldAsync * Changes to return 'option' on some service APIs * fixing tests * fixing surface area test * reseting lazy async * minor name change * Trying to cleanup more incremental builder stuff * fixing a few bugs * trying to fix tests * More cleanup * fixing tests * Fixing build * comment updates and adding a finalize * Minor comment update * Using run synchronously so it can perform cancellation * cleanup * need to reply * Reverting back to the previous AsyncLazy behavior * Cleaning up asynclazy * More comment updates * Remove open * Adding constraint * Allow setting cultureinfo for async lazy * Minor update * re-using compilation globals scope correctly * Added foregroundCheckFileCacheAgent * Fixing deadlock * Minor fix * An incremental build will not invalidate itself if a reference has changed * Added 'autoInvalidateConfiguration' option to FSharpChecker. Added 'IsProjectInvalidated' as a service API. * Fixing builder * Fixing up-to-date check * Update surface area. Renamed IsProjectInvalidated to IsProjectReferencesInvalidated * fixing build * Trying to fix tests * skip test * minor cleanup * Updating surface area. Minor cleanup * Update surface area * Use the parseLock instead of a mailbox * Added AsyncLazy.fs and AsyncLazyTests.fs. Combined AsyncLazyWeak and AsyncLazy into one * More cleanup * Trying to minimize diff * Trying to minimize diff * Removing ctok in more places * Updating baseline. Removing Reactor.fs. * Added a comment * More cleanup * Fixing build * Fixing build * Fixing build * Updated baseline * Remove lock * Fixing tests * Trying to fix tests * Fixing tests * Revert that * Fixing tests * Fixing * Minor format change * Fixing tests * no gc.collect * Trying to fix tests * Trying to fix tests * Using logical * trying to fix tests * updating test sdk * Fixing tests. Reverting back test sdk * Fixing tests * Fixing tests * Fixing test * TcImports uses Async instead of Cancellable now * FrameworkImportCache is now will ensure it only computes once for key * Removing some dependency on ctok * Removed lock in compiler assert * Added AsyncErrorLogger * More work on error logger * more error logger work * Fixed build * Should be partly working * Cleaning up AsyncErrorLogger * minor change * minor fix for debug * Using assemblyResolutionGate to lock * fixing async lazy tests * do not make these type provider tests parallel * do not make these type provider tests parallel * make more tests non-parallelizable * Fixing test * Use getOrCreateBuilder * Make type provider tests non-parallel * Allow cancellation exception to be thrown when evaluating raw contents * Refactored AsyncLazy. Added GraphNode and LazyGraphNode. * Fixing GraphNode * Fixing tests. Adding stack trace info. * fixing build * using string * Reactoring build graph * More refactoring * Fixing build * Removing another mutable state * Bigger buffer time in tests * Ported AsyncLazy from Roslyn * Fixing build * Removed RequestCount * Removed Roslyn AsyncLazy * Skipping tests temporarily until linux passes. GraphNode now will retry by default. * slowly re-enable tests * Re-enable build graph tests * Remove Thread.Sleep in tests. Add timeout exceptions * TcImports locking, use lock/token methodology, remove Enventually, renaming from code review * fix build * fix build * Fixing build * Removed API changes that are returning 'option' in FCS * Allow single background check for a script * Fixing build * Fixing build * Better handling of scripts * fix taking semaphore atomically * comment * Check for task completed * Using explicit continuation options * use underscore Co-authored-by: Don Syme <donsyme@fastmail.com>
The basic idea behind this is to make each file in the dependency graph within incremental builder be asynchronously lazily evaluated; meaning many calls to the same evaluation of a file will not block threads.
eventually
builder.BuildGraph
.Majority of these changes do not change the signature of the public APIs, but may change the behavior slightly due to removing the implicit background building; it's more predictable that way.
This should also resolve:
#11569