-
Notifications
You must be signed in to change notification settings - Fork 790
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
Reduce excess memory usage in TransparentCompiler #17543
base: main
Are you sure you want to change the base?
Changes from 10 commits
d3e5e17
41dd131
419216f
7676fe7
ad9751e
c7949a8
15be216
74162b1
cabf9bd
344e376
e52faa2
d3175b3
a9cd021
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -259,44 +259,138 @@ module private TypeCheckingGraphProcessing = | |
return finalFileResults, state | ||
} | ||
|
||
type internal CompilerCaches(sizeFactor: int) = | ||
type CacheSizes = | ||
{ | ||
ParseFileKeepStrongly: int | ||
ParseFileKeepWeakly: int | ||
ParseFileWithoutProjectKeepStrongly: int | ||
ParseFileWithoutProjectKeepWeakly: int | ||
ParseAndCheckFileInProjectKeepStrongly: int | ||
ParseAndCheckFileInProjectKeepWeakly: int | ||
ParseAndCheckAllFilesInProjectKeepStrongly: int | ||
ParseAndCheckAllFilesInProjectKeepWeakly: int | ||
ParseAndCheckProjectKeepStrongly: int | ||
ParseAndCheckProjectKeepWeakly: int | ||
FrameworkImportsKeepStrongly: int | ||
FrameworkImportsKeepWeakly: int | ||
BootstrapInfoStaticKeepStrongly: int | ||
BootstrapInfoStaticKeepWeakly: int | ||
BootstrapInfoKeepStrongly: int | ||
BootstrapInfoKeepWeakly: int | ||
TcLastFileKeepStrongly: int | ||
TcLastFileKeepWeakly: int | ||
TcIntermediateKeepStrongly: int | ||
TcIntermediateKeepWeakly: int | ||
DependencyGraphKeepStrongly: int | ||
DependencyGraphKeepWeakly: int | ||
ProjectExtrasKeepStrongly: int | ||
ProjectExtrasKeepWeakly: int | ||
AssemblyDataKeepStrongly: int | ||
AssemblyDataKeepWeakly: int | ||
SemanticClassificationKeepStrongly: int | ||
SemanticClassificationKeepWeakly: int | ||
ItemKeyStoreKeepStrongly: int | ||
ItemKeyStoreKeepWeakly: int | ||
ScriptClosureKeepStrongly: int | ||
ScriptClosureKeepWeakly: int | ||
} | ||
|
||
static member Create sizeFactor = | ||
|
||
{ | ||
ParseFileKeepStrongly = 50 * sizeFactor | ||
ParseFileKeepWeakly = 20 * sizeFactor | ||
ParseFileWithoutProjectKeepStrongly = 5 * sizeFactor | ||
ParseFileWithoutProjectKeepWeakly = 2 * sizeFactor | ||
ParseAndCheckFileInProjectKeepStrongly = sizeFactor | ||
ParseAndCheckFileInProjectKeepWeakly = 2 * sizeFactor | ||
ParseAndCheckAllFilesInProjectKeepStrongly = sizeFactor | ||
ParseAndCheckAllFilesInProjectKeepWeakly = 2 * sizeFactor | ||
ParseAndCheckProjectKeepStrongly = sizeFactor | ||
ParseAndCheckProjectKeepWeakly = 2 * sizeFactor | ||
FrameworkImportsKeepStrongly = sizeFactor | ||
FrameworkImportsKeepWeakly = 2 * sizeFactor | ||
BootstrapInfoStaticKeepStrongly = sizeFactor | ||
BootstrapInfoStaticKeepWeakly = 2 * sizeFactor | ||
BootstrapInfoKeepStrongly = sizeFactor | ||
BootstrapInfoKeepWeakly = 2 * sizeFactor | ||
TcLastFileKeepStrongly = sizeFactor | ||
TcLastFileKeepWeakly = 2 * sizeFactor | ||
TcIntermediateKeepStrongly = 20 * sizeFactor | ||
TcIntermediateKeepWeakly = 20 * sizeFactor | ||
DependencyGraphKeepStrongly = sizeFactor | ||
DependencyGraphKeepWeakly = 2 * sizeFactor | ||
ProjectExtrasKeepStrongly = sizeFactor | ||
ProjectExtrasKeepWeakly = 2 * sizeFactor | ||
AssemblyDataKeepStrongly = sizeFactor | ||
AssemblyDataKeepWeakly = 2 * sizeFactor | ||
SemanticClassificationKeepStrongly = sizeFactor | ||
SemanticClassificationKeepWeakly = 2 * sizeFactor | ||
ItemKeyStoreKeepStrongly = sizeFactor | ||
ItemKeyStoreKeepWeakly = 2 * sizeFactor | ||
ScriptClosureKeepStrongly = sizeFactor | ||
ScriptClosureKeepWeakly = 2 * sizeFactor | ||
} | ||
|
||
static member Default = | ||
let sizeFactor = 100 | ||
CacheSizes.Create sizeFactor | ||
|
||
type internal CompilerCaches(sizeFactor: CacheSizes) = | ||
|
||
let sf = sizeFactor | ||
|
||
member _.SizeFactor = sf | ||
member _.CacheSizes = sf | ||
|
||
member val ParseFile = AsyncMemoize(keepStrongly = 50 * sf, keepWeakly = 20 * sf, name = "ParseFile") | ||
member val ParseFile = AsyncMemoize(keepStrongly = sf.ParseFileKeepStrongly, keepWeakly = sf.ParseFileKeepWeakly, name = "ParseFile") | ||
|
||
member val ParseFileWithoutProject = | ||
AsyncMemoize<string, string, FSharpParseFileResults>(keepStrongly = 5 * sf, keepWeakly = 2 * sf, name = "ParseFileWithoutProject") | ||
AsyncMemoize<string, string, FSharpParseFileResults>( | ||
sf.ParseFileWithoutProjectKeepStrongly, | ||
keepWeakly = sf.ParseFileWithoutProjectKeepWeakly, | ||
name = "ParseFileWithoutProject" | ||
) | ||
|
||
member val ParseAndCheckFileInProject = AsyncMemoize(sf, 2 * sf, name = "ParseAndCheckFileInProject") | ||
member val ParseAndCheckFileInProject = | ||
AsyncMemoize( | ||
sf.ParseAndCheckFileInProjectKeepStrongly, | ||
sf.ParseAndCheckFileInProjectKeepWeakly, | ||
name = "ParseAndCheckFileInProject" | ||
) | ||
|
||
member val ParseAndCheckAllFilesInProject = AsyncMemoizeDisabled(sf, 2 * sf, name = "ParseAndCheckFullProject") | ||
member val ParseAndCheckAllFilesInProject = | ||
AsyncMemoizeDisabled( | ||
sf.ParseAndCheckAllFilesInProjectKeepStrongly, | ||
sf.ParseAndCheckAllFilesInProjectKeepWeakly, | ||
name = "ParseAndCheckFullProject" | ||
) | ||
|
||
member val ParseAndCheckProject = AsyncMemoize(sf, 2 * sf, name = "ParseAndCheckProject") | ||
member val ParseAndCheckProject = | ||
AsyncMemoize(sf.ParseAndCheckProjectKeepStrongly, sf.ParseAndCheckProjectKeepWeakly, name = "ParseAndCheckProject") | ||
|
||
member val FrameworkImports = AsyncMemoize(sf, 2 * sf, name = "FrameworkImports") | ||
member val FrameworkImports = AsyncMemoize(sf.FrameworkImportsKeepStrongly, sf.FrameworkImportsKeepWeakly, name = "FrameworkImports") | ||
|
||
member val BootstrapInfoStatic = AsyncMemoize(sf, 2 * sf, name = "BootstrapInfoStatic") | ||
member val BootstrapInfoStatic = | ||
AsyncMemoize(sf.BootstrapInfoStaticKeepStrongly, sf.BootstrapInfoStaticKeepWeakly, name = "BootstrapInfoStatic") | ||
|
||
member val BootstrapInfo = AsyncMemoize(sf, 2 * sf, name = "BootstrapInfo") | ||
member val BootstrapInfo = AsyncMemoize(sf.BootstrapInfoKeepStrongly, sf.BootstrapInfoKeepWeakly, name = "BootstrapInfo") | ||
|
||
member val TcLastFile = AsyncMemoizeDisabled(sf, 2 * sf, name = "TcLastFile") | ||
member val TcLastFile = AsyncMemoizeDisabled(sf.TcLastFileKeepStrongly, sf.TcLastFileKeepWeakly, name = "TcLastFile") | ||
|
||
member val TcIntermediate = AsyncMemoize(20 * sf, 20 * sf, name = "TcIntermediate") | ||
member val TcIntermediate = AsyncMemoize(sf.TcIntermediateKeepStrongly, sf.TcIntermediateKeepWeakly, name = "TcIntermediate") | ||
|
||
member val DependencyGraph = AsyncMemoize(sf, 2 * sf, name = "DependencyGraph") | ||
member val DependencyGraph = AsyncMemoize(sf.DependencyGraphKeepStrongly, sf.DependencyGraphKeepWeakly, name = "DependencyGraph") | ||
|
||
member val ProjectExtras = AsyncMemoizeDisabled(sf, 2 * sf, name = "ProjectExtras") | ||
member val ProjectExtras = AsyncMemoizeDisabled(sf.ProjectExtrasKeepStrongly, sf.ProjectExtrasKeepWeakly, name = "ProjectExtras") | ||
|
||
member val AssemblyData = AsyncMemoize(sf, 2 * sf, name = "AssemblyData") | ||
member val AssemblyData = AsyncMemoize(sf.AssemblyDataKeepStrongly, sf.AssemblyDataKeepWeakly, name = "AssemblyData") | ||
|
||
member val SemanticClassification = AsyncMemoize(sf, 2 * sf, name = "SemanticClassification") | ||
member val SemanticClassification = | ||
AsyncMemoize(sf.SemanticClassificationKeepStrongly, sf.SemanticClassificationKeepWeakly, name = "SemanticClassification") | ||
|
||
member val ItemKeyStore = AsyncMemoize(sf, 2 * sf, name = "ItemKeyStore") | ||
member val ItemKeyStore = AsyncMemoize(sf.ItemKeyStoreKeepStrongly, sf.ItemKeyStoreKeepWeakly, name = "ItemKeyStore") | ||
|
||
member val ScriptClosure = AsyncMemoize(sf, 2 * sf, name = "ScriptClosure") | ||
member val ScriptClosure = AsyncMemoize(sf.ScriptClosureKeepStrongly, sf.ScriptClosureKeepWeakly, name = "ScriptClosure") | ||
|
||
member this.Clear(projects: Set<FSharpProjectIdentifier>) = | ||
let shouldClear project = projects |> Set.contains project | ||
|
@@ -326,7 +420,8 @@ type internal TransparentCompiler | |
parallelReferenceResolution, | ||
captureIdentifiersWhenParsing, | ||
getSource: (string -> Async<ISourceText option>) option, | ||
useChangeNotifications | ||
useChangeNotifications, | ||
?cacheSizes | ||
) as self = | ||
|
||
let documentSource = | ||
|
@@ -337,8 +432,10 @@ type internal TransparentCompiler | |
// Is having just one of these ok? | ||
let lexResourceManager = Lexhelp.LexResourceManager() | ||
|
||
let cacheSizes = defaultArg cacheSizes CacheSizes.Default | ||
|
||
// Mutable so we can easily clear them by creating a new instance | ||
let mutable caches = CompilerCaches(100) | ||
let mutable caches = CompilerCaches(cacheSizes) | ||
|
||
// TODO: do we need this? | ||
//let maxTypeCheckingParallelism = max 1 (Environment.ProcessorCount / 2) | ||
|
@@ -1371,8 +1468,8 @@ type internal TransparentCompiler | |
node, | ||
(fun tcInfo -> | ||
|
||
if tcInfo.stateContainsNodes |> Set.contains fileNode then | ||
failwith $"Oops!" | ||
// if tcInfo.stateContainsNodes |> Set.contains fileNode then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like an unrelated fix. Not sure if it's been discussed elsewhere. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Been discussed in slack before (probably beyond any history now 😢 ). Yeah this could be reverted but I've seen this popup crashing the TC hard. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah. It seems a bit fishy. I need to understand if this is something that should legitimately be happening, clearly previously I thought it shouldn't 😅 |
||
// failwith $"Oops!" | ||
|
||
//if | ||
// tcInfo.stateContainsNodes | ||
|
@@ -1417,14 +1514,8 @@ type internal TransparentCompiler | |
fileNode, | ||
(fun tcInfo -> | ||
|
||
if tcInfo.stateContainsNodes |> Set.contains fileNode then | ||
failwith $"Oops!" | ||
|
||
// if | ||
// tcInfo.stateContainsNodes | ||
// |> Set.contains (NodeToTypeCheck.PhysicalFile(index + 1)) | ||
// then | ||
// failwith $"Oops!!!" | ||
// if tcInfo.stateContainsNodes |> Set.contains fileNode then | ||
// failwith $"Oops!" | ||
|
||
let parsedInput = projectSnapshot.SourceFiles[index].ParsedInput | ||
let prefixPathOpt = None | ||
|
@@ -2087,9 +2178,13 @@ type internal TransparentCompiler | |
|
||
member _.Caches = caches | ||
|
||
member _.SetCacheSizeFactor(sizeFactor: int) = | ||
if sizeFactor <> caches.SizeFactor then | ||
caches <- CompilerCaches(sizeFactor) | ||
member _.SetCacheSize(cacheSize: CacheSizes) = | ||
if cacheSize <> caches.CacheSizes then | ||
caches <- CompilerCaches(cacheSize) | ||
|
||
member x.SetCacheSizeFactor(sizeFactor: int) = | ||
let newCacheSize = CacheSizes.Create sizeFactor | ||
x.SetCacheSize newCacheSize | ||
|
||
interface IBackgroundCompiler with | ||
|
||
|
@@ -2151,7 +2246,7 @@ type internal TransparentCompiler | |
|
||
member _.ClearCaches() : unit = | ||
backgroundCompiler.ClearCaches() | ||
caches <- CompilerCaches(100) // TODO: check | ||
caches <- CompilerCaches(cacheSizes) // TODO: check | ||
|
||
member _.DownsizeCaches() : unit = backgroundCompiler.DownsizeCaches() | ||
|
||
|
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 should be renamed if we keep it like this.