Skip to content

Commit

Permalink
Add knobs and default calculations for .NET 9 DATAS GC Mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
baronfel committed Nov 24, 2024
1 parent 95d6092 commit f045515
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 11 deletions.
13 changes: 9 additions & 4 deletions release/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -585,17 +585,15 @@
"maximum": 9
},
"FSharp.fsac.gc.heapCount": {
"default": 2,
"markdownDescription": "Limits the number of [heaps](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals#the-managed-heap) created by the garbage collector. Applies to server garbage collection only. See [Middle Ground between Server and Workstation GC](https://devblogs.microsoft.com/dotnet/middle-ground-between-server-and-workstation-gc/) for more details. This can allow FSAC to still benefit from Server garbage collection while still limiting the number of heaps. [Only available on .NET 7 or higher](https://github.com/ionide/ionide-vscode-fsharp/issues/1899#issuecomment-1649009462). Requires restart.",
"markdownDescription": "Limits the number of [heaps](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals#the-managed-heap) created by the garbage collector. Applies to server garbage collection only. See [Middle Ground between Server and Workstation GC](https://devblogs.microsoft.com/dotnet/middle-ground-between-server-and-workstation-gc/) for more details. This can allow FSAC to still benefit from Server garbage collection while still limiting the number of heaps. [Only available on .NET 7 or higher](https://github.com/ionide/ionide-vscode-fsharp/issues/1899#issuecomment-1649009462). Requires restart. If FSAC is run on .NET 8 runtimes, this will be set to 2 by default to prevent inflated memory use. On .NET 9 with DATAS enabled, this will not be set. ",
"type": "integer",
"required": [
"FSharp.fsac.gc.server"
]
},
"Fsharp.fsac.gc.noAffinitize": {
"default": true,
"type": "boolean",
"markdownDescription": "Specifies whether to [affinitize](https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#affinitize) garbage collection threads with processors. To affinitize a GC thread means that it can only run on its specific CPU.. Applies to server garbage collection only. See [GCNoAffinitize](https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/gcnoaffinitize-element#remarks) for more details. [Only available on .NET 7 or higher](https://github.com/ionide/ionide-vscode-fsharp/issues/1899#issuecomment-1649009462). Requires restart.",
"markdownDescription": "Specifies whether to [affinitize](https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#affinitize) garbage collection threads with processors. To affinitize a GC thread means that it can only run on its specific CPU.. Applies to server garbage collection only. See [GCNoAffinitize](https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/gcnoaffinitize-element#remarks) for more details. [Only available on .NET 7 or higher](https://github.com/ionide/ionide-vscode-fsharp/issues/1899#issuecomment-1649009462). Requires restart. If FSAC is run on .NET 8 runtimes, this will be set by default. On .NET 9 with DATAS enabled, this will not be set.",
"required": [
"FSharp.fsac.gc.server"
]
Expand All @@ -605,6 +603,13 @@
"markdownDescription": "Configures whether the application uses workstation garbage collection or server garbage collection. See [Workstation vs Server Garbage Collection](https://devblogs.microsoft.com/premier-developer/understanding-different-gc-modes-with-concurrency-visualizer/#workstation-gc-vs-server-gc) for more details. Workstation will use less memory but Server will have more throughput. Requires restart.",
"type": "boolean"
},
"FSharp.fsac.gc.useDatas": {
"markdownDescription": "Configures whether the application uses the DATAS(dynamic adaptation to application sizes) server garbage collection mode. See [DATAS](https://learn.microsoft.com/dotnet/core/runtime-config/garbage-collector#dynamic-adaptation-to-application-sizes-datas) for more details. Requires restart. When FSAC is run on .NET 8 runtimes, this will be set to false by default. On .NET 9 runtimes, this will be set to true by default.",
"type": "boolean",
"required": [
"FSharp.fsac.gc.server"
]
},
"FSharp.fsac.netCoreDllPath": {
"default": "",
"description": "The path to the \u0027fsautocomplete.dll\u0027, a directory containing TFM-specific versions of fsautocomplete.dll, or a directory containing fsautocomplete.dll. Useful for debugging a self-built FSAC. If a DLL is specified, uses it directly. If a directory is specified and it contains TFM-specific folders (net6.0, net7.0, etc) then that directory will be probed for the best TFM to use for the current runtime. This is useful when working with a local copy of FSAC, you can point directly to the bin/Debug or bin/Release folder and it\u0027ll Just Work. Finally, if a directory is specified and there are no TFM paths, then fsautocomplete.dll from that directory is used. Requires restart.",
Expand Down
46 changes: 39 additions & 7 deletions src/Core/LanguageService.fs
Original file line number Diff line number Diff line change
Expand Up @@ -705,11 +705,17 @@ Consider:
| None, Some true -> 9
| None, _ -> 0

let gcHeapCount = "FSharp.fsac.gc.heapCount" |> Configuration.get 2

let gcServer = "FSharp.fsac.gc.server" |> Configuration.get true

let gcNoAffinitize = "Fsharp.fsac.gc.noAffinitize" |> Configuration.get true
let gcServerUseDatas: bool option =
"FSharp.fsac.gc.useDatas" |> Configuration.tryGet |> Option.bind tryBool

let gcNoAffinitize =
"Fsharp.fsac.gc.noAffinitize" |> Configuration.tryGet |> Option.bind tryBool

let gcHeapCount =
"FSharp.fsac.gc.heapCount" |> Configuration.tryGet |> Option.bind tryInt

let parallelReferenceResolution =
"FSharp.fsac.parallelReferenceResolution" |> Configuration.get false
Expand Down Expand Up @@ -866,17 +872,43 @@ Consider:
// Only set DOTNET_GCHeapCount if we're on .NET 7 or higher
// .NET 6 has some issues with this env var on linux
// https://github.com/ionide/ionide-vscode-fsharp/issues/1899
let versionSupportingEnvVars = (semver.parse (Some(U2.Case1 "7.0.0"))).Value

let isNet7orHigher =
semver.cmp (U2.Case2 sdkVersion, Operator.GTE, U2.Case2 versionSupportingEnvVars)
let versionSupportingDATASGCMode = (semver.parse (Some(U2.Case1 "9.0.0"))).Value
let isdotnet8 = sdkVersion.major = 8

let isNet9orHigher =
semver.cmp (U2.Case2 sdkVersion, Operator.GTE, U2.Case2 versionSupportingDATASGCMode)

// datas is on by 9
let useDatas =
match gcServerUseDatas with
| Some b -> b
| None -> isNet9orHigher

let gcNoAffinitize =
match gcNoAffinitize with
| Some b -> b
| None -> isdotnet8 || not useDatas // no need to affinitize on 9 because Datas

let gcHeapCount =
match gcHeapCount with
| Some i -> Some i
| None -> if isdotnet8 then Some 2 else None

let fsacEnvVars =
[ yield! fsacEnvVars
if isNet7orHigher then

if useDatas then
// DATAS and affinitization/heap management seem to be mutually exclusive, so we enforce that here.
yield "DOTNET_GCDynamicAdaptationMode", box (boolToInt useDatas) // https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#dynamic-adaptation-to-application-sizes-datas
else
// it doesn't really make sense to set GCNoAffinitize without setting GCHeapCount
yield "DOTNET_GCNoAffinitize", box (boolToInt gcNoAffinitize) // https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#affinitize
yield "DOTNET_GCHeapCount", box (gcHeapCount.ToString("X")) // Requires hexadecimal value https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#heap-count

yield!
gcHeapCount
|> Option.map (fun hc -> "DOTNET_GCHeapCount", box (hc.ToString("X")))
|> Option.toList // Requires hexadecimal value https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#heap-count

yield "DOTNET_GCConserveMemory", box gcConserveMemory //https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#conserve-memory
yield "DOTNET_GCServer", box (boolToInt gcServer) // https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#workstation-vs-server
Expand Down

0 comments on commit f045515

Please sign in to comment.