question

Hobitten-9205 avatar image
0 Votes"
Hobitten-9205 asked Bruce-SqlWork answered

How do I configure my multithreaded .NET 6 application to use all Windows CPU groups?

I'm trying to migrate a project from .NET Framework 4.7.2 to .NET 6, but the performance of my program has dropped significantly. Parts of the program exploit parallelism for bulk operations on a server with 96 Cores and 192 Logical processors split across 4 CPU groups.

I'm running the program on a Windows Server 2016 with the .NET 6 Runtime installed (.NET 6 SDK not installed). The project is written in F# 6.0.

In .NET Framework 4.7.2 we used the following app.config-file which successfully made the program run across all 192 Logical processors, achieving ~98% CPU utilization:

 <?xml version="1.0" encoding="utf-8"?>
 <configuration>
     <runtime>
         <Thread_UseAllCpuGroups enabled="true" />
         <GCCpuGroup enabled="true" />
         <gcServer enabled="true" />
         <gcAllowVeryLargeObjects enabled="true" />
     </runtime>
 </configuration>


After migrating to .NET 6 (and by extension .NET Core) the CPU utilization dropped, and I am having trouble increasing it again.

According to Microsoft's own documentation app.config is not used to configure .NET Core projects, replaced by [appname].runtimeconfig.json. To accommodate this change i have added a runtimeconfig.template.json to my project:

 {
   "configProperties": {
     "System.GC.CpuGroup": true,
     "System.GC.Server": true,
     "COMPlus_gcAllowVeryLargeObjects": 1
   }
 }

This produces the following [appname].runtimeconfig.json-file:

 {
   "runtimeOptions": {
     "tfm": "net6.0",
     "framework": {
       "name": "Microsoft.NETCore.App",
       "version": "6.0.0"
     },
     "configProperties": {
       "System.GC.CpuGroup": true,
       "System.GC.Server": true,
       "COMPlus_gcAllowVeryLargeObjects": 1
     }
   }
 }

The property System.GC.CpuGroup seems to work, giving me a peak of ~28% CPU utilization by distributing threads across a single CPU Group:

180155-cpu-usage.png

Now I need to distribute threads across different CPU Groups.

Thread_UseAllCpuGroups was omitted due to this documentation saying the variable is N/A in runtimeconfig.json, and must be set as an environment variable.

According to Trying to use Thread_UseAllCpuGroups in a .Net Core app this only works when set at the command line, but i have tried multiple ways of setting it:

  1. CommandLine using set COMPlus_Thread_UseAllCpuGroups=1 before running my program.

  2. Setting the variable though Control Panel -> System and Security -> System -> Environment Variables.

  3. Defining a launchSetting.json-file with the variable and copying it to the output directory.

  4. Manually setting the variable in my program.fs-file using System.Environment.SetEnvironmentVariable("COMPlus_Thread_UseAllCpuGroups", "1").

None of the above methods have worked, and I am unsure what I am doing wrong, especially given how few posts I can find online on this issue.

Finally my question is: How do I make my .NET 6 console application utilize all my logical processors?



dotnet-runtimedotnet-fsharp
cpu-usage.png (28.5 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

Bruce-SqlWork avatar image
0 Votes"
Bruce-SqlWork answered

I'd try f# issues page:

https://github.com/dotnet/fsharp/issues

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.