Skip to content
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

[WIP] Reuse typechecking results - stage 1 #17898

Draft
wants to merge 29 commits into
base: main
Choose a base branch
from

Conversation

psfinaki
Copy link
Member

@psfinaki psfinaki commented Oct 18, 2024

First part of the implementation of reusing typecheck results, as per the design doc.

This basically does 2 things:

  • adds the flag --reusetypecheckingresults, with all the hooking
  • force-generates the typechecking graph and skips recompilation if it's unchanged

Open questions: see my comments.

Copy link
Contributor

github-actions bot commented Oct 18, 2024

❗ Release notes required


✅ Found changes and release notes in following paths:

Warning

No PR link found in some release notes, please consider adding it.

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/9.0.200.md No current pull request URL (#17898) found, please consider adding it

@psfinaki psfinaki changed the title Reuse typechecking results - stage 1 [WIP] Reuse typechecking results - stage 1 Oct 18, 2024
for KeyValue((idx, fileName), _) in graph do
appendLine $"%i{idx}[\"%s{fileName}\"]"

for KeyValue((idx, _), deps) in graph do
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might print something different here, so far this is partially copypasted from the mermaid serialization.

@@ -1961,7 +1961,54 @@ let CheckMultipleInputsUsingGraphMode

partialResults, tcState)

let TryReuseTypecheckingResults (tcConfig: TcConfig) inputs =
let tcDataFileName = FileSystem.GetFullPathShim "FSharpTypecheckingData"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably come from msbuild, via the value of the flag, and should be set to an intermediate output

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I need to resolve and set the proper location for the file here.

The name got inspiration for FSharpSignatureData and FSharpOptimizationData we already have, but it can be whatever.

let existingTcData = tcDataFile.ReadAllText()

if thisTcData = existingTcData then
tcConfig.exiter.Exit 0
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this phase, we don't cache any actual typechecking results yet... So when we detect there is no need for recompilation, there is nothing to restore and propagate yet.

So what do we do here? Just stop? That's weird.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the feature it cannot actually restore typechecking data, it should not do anything. Just signal a bool, ignore it, but do not exit.

Collecting metrics to actually evaluate the hit/miss ratios would be good as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well this we hit not when we cannot restore the data but we don't want to do that. Essentially, when we detect that nothing has changed since the last compilation.

If we ignore it, we will keep recompiling code in such cases. Is that what we want at this stage?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as this feature cannot persist and rehydrate the typechecking results instead of recalculating them - yes, indeed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm okay, removed the exit here. As for the metric - you mean collecting them via events?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some telemetry later telling us "how good" it is in terms of cache hits.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's clear, it's more about the mechanism to use. I only noticed events being used in the compiler which we could probably utilize. Or do you have some other idea?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use activities for now is good enough. Later on we'll hook up dotnet-collect compatible events

@@ -513,6 +513,7 @@ let main1
rangeForErrors = range0
)

tcConfigB.cmdLineArgs <- argv |> String.concat " "
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we need to keep track of the cmd line arguments here. What's the best way to propagate this along the code?

The current mechanism (via globals) forces this to be mutable - which it doesn't have to be, hence I don't like it too much. Alternative would be creating yet another bunch of optional parameters to affected functions all over the compiler - don't like that too much either...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only TcConfigBuilder uses mutable data, since it is a builder.
This information should be propagated to TcConfig or TcGlobals (depending on where it is needed), where things are immutable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No we do propagate it to TcConfig now, that's what's ParseAndCheckInputs uses now.

@psfinaki psfinaki requested a review from T-Gro October 18, 2024 16:31
@psfinaki
Copy link
Member Author

@T-Gro PTAL, this is an early stage so I mostly just wanted to discuss the questions I raised in the comments, so that we go in the agreed direction.

{
Idx = idx
FileName = input.FileName
ParsedInput = input
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general I am missing "lastupdated" timestamps for making the comparison relevant.
Also compiler version or any other header to be a quick circuit breaker in case of newer compiler getting access to older files.

(might even be version/timestamp/.. of Fsharp.Compiler.Service.dll itself I guess?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, I added a notion of this to what we write to the TcData.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: New
Development

Successfully merging this pull request may close these issues.

3 participants