Skip to content

BackgroundCompiler.ParseAndCheckProjectImpl takes a very long time on a big solution with a very connected project dependency graph #538

@oliviermatz

Description

@oliviermatz

I tried to use the "Find all references" feature of F# power tools on a big solution. In certain cases, the analysis would was very slow (I did not measure how slow, I killed devenv.exe after one hour). A quick profiling showed that the FSharp.Compiler.Service spent all its time running IncrementalBuilder.GetLogicalTimeStampForProject. I then tried to reproduce the degenerative behaviour on a simple example and came up with this.

  • A simple solution with 4 projects A, B, C and D.
  • B references A
  • C references A and B
  • D references A, B, and C

Using F# powertools, finding all references on a type defined in A results in :

  • 53 calls of GetLogicalTimeStampForProject on the project A
  • 21 calls of GetLogicalTimeStampForProject on the project B
  • 7 calls of GetLogicalTimeStampForProject on the project C

I understand that the logical timestamp of a project is computed from the last modified timestamp on all of its files, and recursively from the logical timestamp of all the projects it references. So I believe we're faced with an algorithm that is doing IO with exponential complexity.

In my opinion, simply memoizing the logical timestamps of projects during the computation should solve the problem. I may get enough time in the next weeks to try to do it myself but I thought I would share my analysis in the mean time.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions