We have a .net 6.0 server app and the MS docs don't give absolute clarity on how to set up our gen 2 garbage collection so it doesn't suspend all our application threads.
We've put this in our .csproj file:
<PropertyGroup>
<ServerGarbageCollection>true</ServerGarbageCollection>
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
</PropertyGroup>
We build with dotnet publish -c release -r win-x86 --self-contained false ...
(rather than msbuild
, for info) ...
But it doesn't seem to have any effect - we still get suspended threads periodically that correspond to GC.
The docs suggest setting an environment variable and also a runtime json file setting, but just wondering if anybody has the gospel, proven word on how to implement this in .net 6.0 (or upwards)?
In short - it is not possible, there are always cases when collection is blocking (as far as I understand at least anything involving compaction for example).
From the Background garbage collection (the mode for minimizing GC pauses) docs:
A collection on ephemeral generations during background garbage collection is known as foreground garbage collection. When foreground garbage collections occur, all managed threads are suspended.
Note that background garbage collection is enabled by default. From the docs:
Default: Use background GC. This is equivalent to setting the value to true.
And additional info from the "Pro .NET Memory Management" by Konrad Kokosa about the Background Server mode:
- Ephemeral collections are Non-Concurrent GCs - they are fast enough to make them non-concurrently. This also allows them to be compacting if they wish. They are executed by foreground GC threads in parallel - each such thread is responsible for its dedicated Managed Heap.
- A full-GC may be executed in two modes:
- Non-Concurrent GC - because of the “stop the world” nature, it may be compacting. Like in the ephemeral collection, all Server GC threads are executing such GC in parallel.
- Background GC - it executes most of the work while managed threads are normally executed. This mode is not compacting. As in Background Workstation case, this GC is executed by dedicated background GC threads (in parallel).
- Background full-GC has the following additional characteristics:
- User-managed threads can allocate objects during its work - and these allocations can trigger ephemeral collections (Foreground GCs)
- Foreground GCs may happen many times during a Background GC
- It contains two short “stop the world” phases - at the beginning and in the middle of the GC
If you want full control over collection and prevent GC pauses then managed language is not a right tool for the job.
There are techniques to minimize/shorten the GC pauses:
stackalloc
's, switching to struct
's, etc.)