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

Hobitten 11 Reputation points
2022-03-04T16:28:59.653+00:00

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?

.NET Runtime
.NET Runtime
.NET: Microsoft Technologies based on the .NET software framework.Runtime: An environment required to run apps that aren't compiled to machine language.
1,119 questions
.NET F#
.NET F#
.NET: Microsoft Technologies based on the .NET software framework.F#: A strongly typed, multi-paradigm programming language developed by the F# Software Foundation, Microsoft, and open contributors.
92 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 55,686 Reputation points
    2022-03-04T16:51:29.107+00:00
    0 comments No comments