Skip to content

Experiment: Plug caches in #18468

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

Closed
wants to merge 51 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
2e8000f
add caches
majocha Apr 10, 2025
17f2d93
plug it in
majocha Apr 10, 2025
17d2cbb
internal
majocha Apr 10, 2025
3a0352c
Merge branch 'main' into plug-caches-in
majocha Apr 10, 2025
ced43c5
ok
majocha Apr 10, 2025
08d3730
trace count in incremental use
majocha Apr 12, 2025
7d10f96
Merge branch 'main' into plug-caches-in
majocha Apr 12, 2025
ffd764d
show count in release config too
majocha Apr 12, 2025
1640e43
Merge branch 'plug-caches-in' of https://github.com/majocha/fsharp in…
majocha Apr 12, 2025
5f2c535
tune cache
majocha Apr 12, 2025
a7d4605
fantomas
majocha Apr 12, 2025
7d9746a
ilver
majocha Apr 12, 2025
238a92a
fix sa again
majocha Apr 13, 2025
1d21c78
just CWT for now
majocha Apr 13, 2025
03dc52b
add some ids to see whats what
majocha Apr 13, 2025
d524663
for some reason it didnt work
majocha Apr 13, 2025
e130e01
metrics
majocha Apr 14, 2025
47b4165
metrics
majocha Apr 14, 2025
90eaa02
one cache instance per TcGlobals
majocha Apr 14, 2025
165ea24
fix no eviction when OneOff
majocha Apr 14, 2025
83208ac
restore LanguageFeature
majocha Apr 14, 2025
4659934
singleton, but compilationMode aware
majocha Apr 14, 2025
5abed61
fix background eviction
majocha Apr 14, 2025
a679a7f
Merge branch 'main' into plug-caches-in
majocha Apr 14, 2025
e1a48ff
wip
majocha Apr 14, 2025
e1cd30b
more metrics
majocha Apr 14, 2025
7bdde6a
background eviction needs work
majocha Apr 15, 2025
ee872ca
Merge branch 'main' into plug-caches-in
majocha Apr 17, 2025
e6ba27e
fix stampEquals
majocha Apr 17, 2025
5b87356
fix hash
majocha Apr 17, 2025
039cc9a
improve allocations etc
majocha Apr 17, 2025
0e8e6cb
format
majocha Apr 17, 2025
474081a
ilverify
majocha Apr 17, 2025
c0ddd92
fix
majocha Apr 18, 2025
fdf1916
smaller cache
majocha Apr 18, 2025
520c770
wip
majocha Apr 18, 2025
f01ac19
hit ratio
majocha Apr 18, 2025
43cbdce
wip
majocha Apr 19, 2025
8677d4f
wip
majocha Apr 21, 2025
245460f
some cleanup
majocha Apr 22, 2025
56eab5a
metrics
majocha Apr 23, 2025
b5f08cf
Merge branch 'main' into plug-caches-in
majocha Apr 23, 2025
64b6107
add signature
majocha Apr 23, 2025
905fe52
fix
majocha Apr 23, 2025
6e21777
eviction
majocha Apr 23, 2025
83d8122
output
majocha Apr 23, 2025
2c81e17
back to singleton
majocha Apr 24, 2025
f9ab164
otel
majocha Apr 24, 2025
6e6ca75
fix
majocha Apr 24, 2025
95f6e56
Merge branch 'main' into plug-caches-in
majocha Apr 24, 2025
619dbd4
fixfix
majocha Apr 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/Compiler/Checking/TypeRelations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ let TypesFeasiblyEquivStripMeasures g amap m ty1 ty2 =
TypesFeasiblyEquivalent true 0 g amap m ty1 ty2

let inline TryGetCachedTypeSubsumption (g: TcGlobals) (amap: ImportMap) key =
if g.compilationMode = CompilationMode.OneOff && g.langVersion.SupportsFeature LanguageFeature.UseTypeSubsumptionCache then
if g.langVersion.SupportsFeature LanguageFeature.UseTypeSubsumptionCache then
match amap.TypeSubsumptionCache.TryGetValue(key) with
| true, subsumes ->
ValueSome subsumes
Expand All @@ -112,8 +112,8 @@ let inline TryGetCachedTypeSubsumption (g: TcGlobals) (amap: ImportMap) key =
ValueNone

let inline UpdateCachedTypeSubsumption (g: TcGlobals) (amap: ImportMap) key subsumes : unit =
if g.compilationMode = CompilationMode.OneOff && g.langVersion.SupportsFeature LanguageFeature.UseTypeSubsumptionCache then
amap.TypeSubsumptionCache[key] <- subsumes
if g.langVersion.SupportsFeature LanguageFeature.UseTypeSubsumptionCache then
amap.TypeSubsumptionCache.AddOrUpdate(key, subsumes)

/// The feasible coercion relation. Part of the language spec.
let rec TypeFeasiblySubsumesType ndeep (g: TcGlobals) (amap: ImportMap) m (ty1: TType) (canCoerce: CanCoerce) (ty2: TType) =
Expand All @@ -125,7 +125,7 @@ let rec TypeFeasiblySubsumesType ndeep (g: TcGlobals) (amap: ImportMap) m (ty1:
let ty2 = stripTyEqns g ty2

// Check if language feature supported
let key = TTypeCacheKey.FromStrippedTypes (ty1, ty2, canCoerce, g)
let key = TTypeCacheKey.FromStrippedTypes (ty1, ty2, canCoerce)

match TryGetCachedTypeSubsumption g amap key with
| ValueSome subsumes ->
Expand Down
66 changes: 46 additions & 20 deletions src/Compiler/Checking/import.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,22 @@ module internal FSharp.Compiler.Import
open System.Collections.Concurrent
open System.Collections.Generic
open System.Collections.Immutable
open FSharp.Compiler.Text.Range
open System.Diagnostics
open System.Runtime.CompilerServices
open System.Threading

open Internal.Utilities.Library
open Internal.Utilities.Library.Extras
open Internal.Utilities.TypeHashing
open Internal.Utilities.TypeHashing.HashTypes

open FSharp.Compiler
open FSharp.Compiler.AbstractIL.IL
open FSharp.Compiler.CompilerGlobalState
open FSharp.Compiler.DiagnosticsLogger
open FSharp.Compiler.SyntaxTreeOps
open FSharp.Compiler.Text
open FSharp.Compiler.Text.Range
open FSharp.Compiler.Xml
open FSharp.Compiler.TypedTree
open FSharp.Compiler.TypedTreeBasics
Expand Down Expand Up @@ -52,18 +57,18 @@ type CanCoerce =
| CanCoerce
| NoCoerce

type [<Struct; NoComparison; CustomEquality>] TTypeCacheKey =
[<Struct; NoComparison; CustomEquality; DebuggerDisplay("{ToString()}")>]
type TTypeCacheKey =

val ty1: TType
val ty2: TType
val canCoerce: CanCoerce
val tcGlobals: TcGlobals

private new (ty1, ty2, canCoerce, tcGlobals) =
{ ty1 = ty1; ty2 = ty2; canCoerce = canCoerce; tcGlobals = tcGlobals }
private new (ty1, ty2, canCoerce) =
{ ty1 = ty1; ty2 = ty2; canCoerce = canCoerce }

static member FromStrippedTypes (ty1, ty2, canCoerce, tcGlobals) =
TTypeCacheKey(ty1, ty2, canCoerce, tcGlobals)
static member FromStrippedTypes (ty1, ty2, canCoerce) =
TTypeCacheKey(ty1, ty2, canCoerce)

interface System.IEquatable<TTypeCacheKey> with
member this.Equals other =
Expand All @@ -72,23 +77,46 @@ type [<Struct; NoComparison; CustomEquality>] TTypeCacheKey =
elif this.ty1 === other.ty1 && this.ty2 === other.ty2 then
true
else
stampEquals this.tcGlobals this.ty1 other.ty1
&& stampEquals this.tcGlobals this.ty2 other.ty2
HashStamps.stampEquals this.ty1 other.ty1
&& HashStamps.stampEquals this.ty2 other.ty2

override this.Equals(other:objnull) =
match other with
| :? TTypeCacheKey as p -> (this :> System.IEquatable<TTypeCacheKey>).Equals p
| _ -> false

override this.GetHashCode() : int =
let g = this.tcGlobals

let ty1Hash = combineHash (hashStamp g this.ty1) (hashTType g this.ty1)
let ty2Hash = combineHash (hashStamp g this.ty2) (hashTType g this.ty2)

let combined = combineHash (combineHash ty1Hash ty2Hash) (hash this.canCoerce)

combined
HashStamps.hashTType this.ty1
|> pipeToHash (HashStamps.hashTType this.ty2)
|> pipeToHash (hash this.canCoerce)

override this.ToString () = $"{this.ty1.DebugText}-{this.ty2.DebugText}"

let getOrCreateTypeSubsumptionCache =
let mutable lockObj = obj()
let mutable cache = None

fun compilationMode ->
lock lockObj <| fun () ->
match cache with
| Some c -> c
| _ ->
let options =
match compilationMode with
| CompilationMode.OneOff ->
// This is a one-off compilation, so we don't need to worry about eviction.
{ CacheOptions.Default with
MaximumCapacity = 200_000
EvictionMethod = EvictionMethod.NoEviction }
| _ ->
// Oncremental use, so we need to set up the cache with eviction.
{ CacheOptions.Default with
EvictionMethod = EvictionMethod.Background
Strategy = CachingStrategy.LRU
PercentageToEvict = 5
MaximumCapacity = 4 * 32768 }
cache <- Some (Cache.Create<TTypeCacheKey, bool>(options))
cache.Value

//-------------------------------------------------------------------------
// Import an IL types as F# types.
Expand All @@ -106,15 +134,13 @@ type [<Struct; NoComparison; CustomEquality>] TTypeCacheKey =
type ImportMap(g: TcGlobals, assemblyLoader: AssemblyLoader) =
let typeRefToTyconRefCache = ConcurrentDictionary<ILTypeRef, TyconRef>()

let typeSubsumptionCache = ConcurrentDictionary<TTypeCacheKey, bool>(System.Environment.ProcessorCount, 1024)

member _.g = g

member _.assemblyLoader = assemblyLoader

member _.ILTypeRefToTyconRefCache = typeRefToTyconRefCache

member _.TypeSubsumptionCache = typeSubsumptionCache
member val TypeSubsumptionCache: Cache<TTypeCacheKey, bool> = getOrCreateTypeSubsumptionCache g.compilationMode

let CanImportILScopeRef (env: ImportMap) m scoref =

Expand Down
9 changes: 4 additions & 5 deletions src/Compiler/Checking/import.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,14 @@ type CanCoerce =
[<Struct; NoComparison; CustomEquality>]
type TTypeCacheKey =
interface System.IEquatable<TTypeCacheKey>
private new: ty1: TType * ty2: TType * canCoerce: CanCoerce * tcGlobals: TcGlobals -> TTypeCacheKey
private new: ty1: TType * ty2: TType * canCoerce: CanCoerce -> TTypeCacheKey

static member FromStrippedTypes:
ty1: TType * ty2: TType * canCoerce: CanCoerce * tcGlobals: TcGlobals -> TTypeCacheKey
static member FromStrippedTypes: ty1: TType * ty2: TType * canCoerce: CanCoerce -> TTypeCacheKey

val ty1: TType
val ty2: TType
val canCoerce: CanCoerce
val tcGlobals: TcGlobals
//val tcGlobals: TcGlobals
override GetHashCode: unit -> int

/// Represents a context used for converting AbstractIL .NET and provided types to F# internal compiler data structures.
Expand All @@ -73,7 +72,7 @@ type ImportMap =
member g: TcGlobals

/// Type subsumption cache
member TypeSubsumptionCache: ConcurrentDictionary<TTypeCacheKey, bool>
member TypeSubsumptionCache: Cache<TTypeCacheKey, bool>

module Nullness =

Expand Down
2 changes: 2 additions & 0 deletions src/Compiler/FSharp.Compiler.Service.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@
<Compile Include="Utilities\lib.fsi" />
<Compile Include="Utilities\lib.fs" />
<Compile Include="Utilities\DependencyGraph.fs" />
<Compile Include="utilities\Caches.fsi" />
<Compile Include="utilities\Caches.fs" />
<Compile Include="Utilities\LruCache.fsi" />
<Compile Include="Utilities\LruCache.fs" />
<Compile Include="Utilities\ImmutableArray.fsi" />
Expand Down
Loading
Loading