Skip to content

Commit f045515

Browse files
committed
Add knobs and default calculations for .NET 9 DATAS GC Mode.
1 parent 95d6092 commit f045515

File tree

2 files changed

+48
-11
lines changed

2 files changed

+48
-11
lines changed

release/package.json

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -585,17 +585,15 @@
585585
"maximum": 9
586586
},
587587
"FSharp.fsac.gc.heapCount": {
588-
"default": 2,
589-
"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.",
588+
"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. ",
590589
"type": "integer",
591590
"required": [
592591
"FSharp.fsac.gc.server"
593592
]
594593
},
595594
"Fsharp.fsac.gc.noAffinitize": {
596-
"default": true,
597595
"type": "boolean",
598-
"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.",
596+
"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.",
599597
"required": [
600598
"FSharp.fsac.gc.server"
601599
]
@@ -605,6 +603,13 @@
605603
"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.",
606604
"type": "boolean"
607605
},
606+
"FSharp.fsac.gc.useDatas": {
607+
"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.",
608+
"type": "boolean",
609+
"required": [
610+
"FSharp.fsac.gc.server"
611+
]
612+
},
608613
"FSharp.fsac.netCoreDllPath": {
609614
"default": "",
610615
"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.",

src/Core/LanguageService.fs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -705,11 +705,17 @@ Consider:
705705
| None, Some true -> 9
706706
| None, _ -> 0
707707

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

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

712-
let gcNoAffinitize = "Fsharp.fsac.gc.noAffinitize" |> Configuration.get true
711+
let gcServerUseDatas: bool option =
712+
"FSharp.fsac.gc.useDatas" |> Configuration.tryGet |> Option.bind tryBool
713+
714+
let gcNoAffinitize =
715+
"Fsharp.fsac.gc.noAffinitize" |> Configuration.tryGet |> Option.bind tryBool
716+
717+
let gcHeapCount =
718+
"FSharp.fsac.gc.heapCount" |> Configuration.tryGet |> Option.bind tryInt
713719

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

871-
let isNet7orHigher =
872-
semver.cmp (U2.Case2 sdkVersion, Operator.GTE, U2.Case2 versionSupportingEnvVars)
876+
let versionSupportingDATASGCMode = (semver.parse (Some(U2.Case1 "9.0.0"))).Value
877+
let isdotnet8 = sdkVersion.major = 8
878+
879+
let isNet9orHigher =
880+
semver.cmp (U2.Case2 sdkVersion, Operator.GTE, U2.Case2 versionSupportingDATASGCMode)
881+
882+
// datas is on by 9
883+
let useDatas =
884+
match gcServerUseDatas with
885+
| Some b -> b
886+
| None -> isNet9orHigher
887+
888+
let gcNoAffinitize =
889+
match gcNoAffinitize with
890+
| Some b -> b
891+
| None -> isdotnet8 || not useDatas // no need to affinitize on 9 because Datas
892+
893+
let gcHeapCount =
894+
match gcHeapCount with
895+
| Some i -> Some i
896+
| None -> if isdotnet8 then Some 2 else None
873897

874898
let fsacEnvVars =
875899
[ yield! fsacEnvVars
876-
if isNet7orHigher then
900+
901+
if useDatas then
902+
// DATAS and affinitization/heap management seem to be mutually exclusive, so we enforce that here.
903+
yield "DOTNET_GCDynamicAdaptationMode", box (boolToInt useDatas) // https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#dynamic-adaptation-to-application-sizes-datas
904+
else
877905
// it doesn't really make sense to set GCNoAffinitize without setting GCHeapCount
878906
yield "DOTNET_GCNoAffinitize", box (boolToInt gcNoAffinitize) // https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#affinitize
879-
yield "DOTNET_GCHeapCount", box (gcHeapCount.ToString("X")) // Requires hexadecimal value https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#heap-count
907+
908+
yield!
909+
gcHeapCount
910+
|> Option.map (fun hc -> "DOTNET_GCHeapCount", box (hc.ToString("X")))
911+
|> Option.toList // Requires hexadecimal value https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector#heap-count
880912

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

0 commit comments

Comments
 (0)