|
| 1 | +# Parallel Type-Checking in F# |
| 2 | + |
| 3 | +This document describes the idea and implementation details for parallel type-checking of files in the F# compiler. |
| 4 | + |
| 5 | +## Context and the current state of the compiler |
| 6 | + |
| 7 | +Performance of F# compilation and code analysis is not very high. |
| 8 | + |
| 9 | +Recent improvements not-withstanding, there are still low-hanging fruit that can be introduced. |
| 10 | + |
| 11 | +One idea for such an improvement was originally described in https://github.com/dotnet/fsharp/discussions/11634 by @kerams . |
| 12 | +This is going to be the main topic of this page. |
| 13 | + |
| 14 | +### Current state of type-checking |
| 15 | + |
| 16 | +One of the main phases of compilation is type-checking. Depending on the project in question, it can take up to and exceed 50% of the total compilation time. |
| 17 | +Currently, by default all files in a project are type-checked in sequence, one-by-one, leading to increased compilation wall-clock time. |
| 18 | + |
| 19 | +### Recent addition - "Parallel type checking for impl files with backing sig files" |
| 20 | + |
| 21 | +A recent [change](https://github.com/dotnet/fsharp/pull/13737) introduced in the compiler allows for parallel type-checking of all `.fs` files backed by `.fsi` files. Such `.fs` files by definition cannot be depended upon by any other files w.r.t. type-checking, since all the type-checking information is exposed by the corresponding `.fsi` files. |
| 22 | + |
| 23 | +The new feature, when enabled, allows partial parallelisation of type-checking as follows: |
| 24 | +1. All `.fsi` files and `.fs` files without backing `.fsi` files are type-checked in sequence, as before. |
| 25 | +2. Then all `.fs` files with backing `.fsi` files are type-checked in parallel. |
| 26 | + |
| 27 | +For a project that uses `.fsi` files throughout, such as the `FSharp.Compiler.Service` project, this presents a major speedup. |
| 28 | + |
| 29 | +Some data points: |
| 30 | +- [Fantomas](https://github.com/fsprojects/fantomas) solution: total build time 17.49s -> 14.28s - [link](https://github.com/dotnet/fsharp/pull/13737#issuecomment-1223637818) |
| 31 | +- F# codebase build time: 112s -> 92s - [link](https://github.com/dotnet/fsharp/pull/13737#issuecomment-1223386853) |
| 32 | + |
| 33 | +#### Enabling the feature |
| 34 | + |
| 35 | +The feature is opt-in and can be enabled in the compiler via a CLI arg & MSBuild property. |
| 36 | + |
| 37 | +## The importance of using Server GC for parallel work |
| 38 | + |
| 39 | +By default .NET processes use Workstation GC, which is single-threaded. What this means is it can become a bottleneck for highly-parallel operations, due to increased GC pressure and the cost of GC pauses being multiplied by the number of threads waiting. |
| 40 | +That is why when increasing parallelisation of the compiler and the compiler service it is important to note the GC mode being used and consider enabling Server GC. |
| 41 | + |
| 42 | +Below is an example showing the difference it can make for a parallel workflow. |
| 43 | + |
| 44 | +### Parallel projects analysis results for a synthetic solution |
| 45 | +| GC Mode | Processing Mode | Time | |
| 46 | +|-------------|-----------------|-----------------------------------------| |
| 47 | +| Workstation | Sequential | 16005ms | |
| 48 | +| Workstation | Parallel | 10849ms | |
| 49 | +| Server | Sequential | 14594ms (-9% vs Workstation Sequential) | |
| 50 | +| Server | Parallel | 2659ms (-75% vs Workstation Parallel) | |
| 51 | + |
| 52 | +For more details see https://github.com/dotnet/fsharp/pull/13521 |
| 53 | + |
| 54 | +### |
0 commit comments