You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When the process is affinitized on startup, the behavior of Environment.ProcessorCount currently differs between Windows and Linux. On Linux, the property returns the number of processors available according to the affinity mask. On Windows, the property returns the number of processors configured in the system and ignores the affinity mask. The property is often used to determine the amount of parallelism to use in the process, and it has been observed that not limiting the property's value based on affinitization can lead to worse performance.
On Linux, CPU resource limits placed through cgroups also affect the value returned by the property, as we have found through trial-and-error that returning the restricted number of processors from this property is the most appropriate behavior that makes most callers work well.
Goal
Have Environment.ProcessorCount return a value that represents an appropriate level of parallelism that may be used in the process based on affinitization and CPU resource limits
Have the property return a consistent value in comparable relevant configuration between Windows and Linux
Behavior before change
On a machine with 8 logical processors:
When the process is affinitized to 1 logical processor:
Windows: Environment.ProcessorCount == 8
Linux: Environment.ProcessorCount == 1
When CPU resources for the process are limited to the equivalent of 1 logical processor:
When the process is affinitized to 1 logical processor:
Windows: Environment.ProcessorCount == 1
Linux: Environment.ProcessorCount == 1
When CPU resources for the process are limited to the equivalent of 1 logical processor:
Windows: Environment.ProcessorCount == 8
Linux: Environment.ProcessorCount == 1
Behavior after other such issues are fixed (no PR yet)
When the process is affinitized to 1 logical processor:
Windows: Environment.ProcessorCount == 1
Linux: Environment.ProcessorCount == 1
When CPU resources for the process are limited to the equivalent of 1 logical processor:
Windows: Environment.ProcessorCount == 1
Linux: Environment.ProcessorCount == 1
Versions affected
.NET 6
Potential breaks on Windows and workarounds
Code that uses Environment.ProcessorCount and scales down parallelism based on other app or system configuration (including potentially the process' affinity mask) may end up using lower parallelism than intended
Workaround may be to update the application's parallelism scaling
Code that expects Environment.ProcessorCount to return the configured logical processor count may have unexpected results. For example code that verifies that the process is not started affinitized by comparing the affinitized processor count to Environment.ProcessorCount would fail to detect affinitized startup because the comparison would be equal. Or the process may intend to display the total processor count.
Workaround may be to pinvoke to get the total processor count. May not be ideal. Providing full information in other APIs would need discussion to determine what to provide, for example, number of processors configured in the system, number of processors that are online/offline, number of processors the process is affinitized to, CPU quota limits, etc.
Code that happens to perform worse when the value returned by Environment.ProcessorCount is limited by affinitization or CPU resource limits
If these become common, it may be necessary to provide a workaround, such as to provide a way to configure what Environment.ProcessorCount would return, or to provide other APIs
Currently, a config option is not provided to revert the behavior. The difference in behavior between Windows and Linux existed in .NET 5 and below, where Linux has not offered a config option to provide the total processor count, so there hasn't been a workaround for the above issues on Linux so far.
Non-breaking
The thread pool already took affinitization into account in the default parallelization it uses on Windows, when the process is not configured to use multiple CPU groups (the default). In .NET 6 thread pool worker thread management was migrated to managed code and uses Environment.ProcessorCount, so after Update Environment.ProcessorCount on Windows to take into account the processor affinity mask #45943 thread pool worker thread parallelization in .NET 6 would be the same as before in that scenario.
When the process is affinitized on startup, the behavior of
Environment.ProcessorCountcurrently differs between Windows and Linux. On Linux, the property returns the number of processors available according to the affinity mask. On Windows, the property returns the number of processors configured in the system and ignores the affinity mask. The property is often used to determine the amount of parallelism to use in the process, and it has been observed that not limiting the property's value based on affinitization can lead to worse performance.On Linux, CPU resource limits placed through cgroups also affect the value returned by the property, as we have found through trial-and-error that returning the restricted number of processors from this property is the most appropriate behavior that makes most callers work well.
Goal
Environment.ProcessorCountreturn a value that represents an appropriate level of parallelism that may be used in the process based on affinitization and CPU resource limitsBehavior before change
On a machine with 8 logical processors:
Environment.ProcessorCount == 8Environment.ProcessorCount == 1Environment.ProcessorCount == 8Environment.ProcessorCount == 1Behavior after #45943
Environment.ProcessorCount == 1Environment.ProcessorCount == 1Environment.ProcessorCount == 8Environment.ProcessorCount == 1Behavior after other such issues are fixed (no PR yet)
Environment.ProcessorCount == 1Environment.ProcessorCount == 1Environment.ProcessorCount == 1Environment.ProcessorCount == 1Versions affected
.NET 6
Potential breaks on Windows and workarounds
Environment.ProcessorCountand scales down parallelism based on other app or system configuration (including potentially the process' affinity mask) may end up using lower parallelism than intendedEnvironment.ProcessorCountto return the configured logical processor count may have unexpected results. For example code that verifies that the process is not started affinitized by comparing the affinitized processor count toEnvironment.ProcessorCountwould fail to detect affinitized startup because the comparison would be equal. Or the process may intend to display the total processor count.Environment.ProcessorCountis limited by affinitization or CPU resource limitsEnvironment.ProcessorCountwould return, or to provide other APIsCurrently, a config option is not provided to revert the behavior. The difference in behavior between Windows and Linux existed in .NET 5 and below, where Linux has not offered a config option to provide the total processor count, so there hasn't been a workaround for the above issues on Linux so far.
Non-breaking
Environment.ProcessorCount, so after UpdateEnvironment.ProcessorCounton Windows to take into account the processor affinity mask #45943 thread pool worker thread parallelization in .NET 6 would be the same as before in that scenario.