From 4cbd7a16fc49c9d179dad11984579337f0d43726 Mon Sep 17 00:00:00 2001 From: Anton Lapounov Date: Thu, 28 Apr 2022 00:08:52 -0700 Subject: [PATCH 1/2] Use all processor groups if the process is not affinitized to a single one --- src/coreclr/utilcode/util.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/coreclr/utilcode/util.cpp b/src/coreclr/utilcode/util.cpp index 2d2d2d22de2ec1..b43853207d0059 100644 --- a/src/coreclr/utilcode/util.cpp +++ b/src/coreclr/utilcode/util.cpp @@ -760,7 +760,15 @@ DWORD LCM(DWORD u, DWORD v) CONTRACTL_END; #if !defined(FEATURE_NATIVEAOT) && (defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)) - BOOL enableGCCPUGroups = Configuration::GetKnobBooleanValue(W("System.GC.CpuGroup"), CLRConfig::EXTERNAL_GCCpuGroup); + USHORT groupCount = 0; + + // Starting with Windows 11 and Windows Server 2022, a process is no longer restricted to a single processor group + // by default. Use all processor groups if the process is not affinitized to a single one. + if (GetProcessGroupAffinity(GetCurrentProcess(), &groupCount, NULL) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) + groupCount = 1; + + BOOL enableGCCPUGroups = groupCount > 1 || + Configuration::GetKnobBooleanValue(W("System.GC.CpuGroup"), CLRConfig::EXTERNAL_GCCpuGroup); if (!enableGCCPUGroups) return; @@ -772,7 +780,7 @@ DWORD LCM(DWORD u, DWORD v) if (m_nGroups > 1) { m_enableGCCPUGroups = TRUE; - m_threadUseAllCpuGroups = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Thread_UseAllCpuGroups) != 0; + m_threadUseAllCpuGroups = groupCount > 1 || CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Thread_UseAllCpuGroups) != 0; m_threadAssignCpuGroups = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Thread_AssignCpuGroups) != 0; // Save the processor group affinity of the initial thread From c8dcb340f1b80bbade4a13bb8798cff7b5539d9f Mon Sep 17 00:00:00 2001 From: Anton Lapounov Date: Tue, 9 Aug 2022 23:04:39 -0700 Subject: [PATCH 2/2] Allow to override default behavior on Windows 11+ --- src/coreclr/inc/configuration.h | 14 +++++++++++--- src/coreclr/utilcode/configuration.cpp | 12 ++++++++++++ src/coreclr/utilcode/util.cpp | 11 ++++++----- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/coreclr/inc/configuration.h b/src/coreclr/inc/configuration.h index bf2d805e049b92..cfc7dcd5819a15 100644 --- a/src/coreclr/inc/configuration.h +++ b/src/coreclr/inc/configuration.h @@ -33,7 +33,9 @@ class Configuration // Unfortunately our traditional config system insists on interpreting numbers as 32-bit so interpret the config // in the traditional way separately if you need to. // - // Returns value for name if found in config. + // Returns (in priority order): + // - The value of the ConfigurationKnob (searched by name) if it's set (performs a _wcstoui64) + // - The default value passed in static ULONGLONG GetKnobULONGLONGValue(LPCWSTR name, ULONGLONG defaultValue); // Returns (in priority order): @@ -48,11 +50,17 @@ class Configuration static LPCWSTR GetKnobStringValue(LPCWSTR name); // Returns (in priority order): - // - The value of the ConfigDWORDInfo if it's set (1 is true, anything else is false) + // - The value of the ConfigDWORDInfo if it's set (0 is false, anything else is true) // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcscmp with "true"). - // - The default set in the ConfigDWORDInfo (1 is true, anything else is false) + // - The default set in the ConfigDWORDInfo (0 is false, anything else is true) static bool GetKnobBooleanValue(LPCWSTR name, const CLRConfig::ConfigDWORDInfo& dwordInfo); + // Returns (in priority order): + // - The value of the ConfigDWORDInfo if it's set (0 is false, anything else is true) + // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcscmp with "true"). + // - The default value passed in + static bool GetKnobBooleanValue(LPCWSTR name, const CLRConfig::ConfigDWORDInfo& dwordInfo, bool defaultValue); + // Returns (in priority order): // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcscmp with "true"). // - The default value passed in diff --git a/src/coreclr/utilcode/configuration.cpp b/src/coreclr/utilcode/configuration.cpp index 50a5e335a742b9..170edc5b273bc2 100644 --- a/src/coreclr/utilcode/configuration.cpp +++ b/src/coreclr/utilcode/configuration.cpp @@ -123,6 +123,18 @@ bool Configuration::GetKnobBooleanValue(LPCWSTR name, const CLRConfig::ConfigDWO return (legacyValue != 0); } +bool Configuration::GetKnobBooleanValue(LPCWSTR name, const CLRConfig::ConfigDWORDInfo& dwordInfo, bool defaultValue) +{ + bool returnedDefaultValue; + DWORD legacyValue = CLRConfig::GetConfigValue(dwordInfo, &returnedDefaultValue); + if (!returnedDefaultValue) + { + return (legacyValue != 0); + } + + return GetKnobBooleanValue(name, defaultValue); +} + bool Configuration::GetKnobBooleanValue(LPCWSTR name, bool defaultValue) { LPCWSTR knobValue = GetConfigurationValue(name); diff --git a/src/coreclr/utilcode/util.cpp b/src/coreclr/utilcode/util.cpp index b43853207d0059..623ef923516ce5 100644 --- a/src/coreclr/utilcode/util.cpp +++ b/src/coreclr/utilcode/util.cpp @@ -762,13 +762,14 @@ DWORD LCM(DWORD u, DWORD v) #if !defined(FEATURE_NATIVEAOT) && (defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)) USHORT groupCount = 0; - // Starting with Windows 11 and Windows Server 2022, a process is no longer restricted to a single processor group - // by default. Use all processor groups if the process is not affinitized to a single one. + // On Windows 11+ and Windows Server 2022+, a process is no longer restricted to a single processor group by default. + // If more than one processor group is available to the process (a non-affinitized process on Windows 11+), + // default to using multiple processor groups; otherwise, default to using a single processor group. This default + // behavior may be overridden by the configuration values below. if (GetProcessGroupAffinity(GetCurrentProcess(), &groupCount, NULL) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) groupCount = 1; - BOOL enableGCCPUGroups = groupCount > 1 || - Configuration::GetKnobBooleanValue(W("System.GC.CpuGroup"), CLRConfig::EXTERNAL_GCCpuGroup); + BOOL enableGCCPUGroups = Configuration::GetKnobBooleanValue(W("System.GC.CpuGroup"), CLRConfig::EXTERNAL_GCCpuGroup, groupCount > 1); if (!enableGCCPUGroups) return; @@ -780,7 +781,7 @@ DWORD LCM(DWORD u, DWORD v) if (m_nGroups > 1) { m_enableGCCPUGroups = TRUE; - m_threadUseAllCpuGroups = groupCount > 1 || CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Thread_UseAllCpuGroups) != 0; + m_threadUseAllCpuGroups = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Thread_UseAllCpuGroups, groupCount > 1) != 0; m_threadAssignCpuGroups = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_Thread_AssignCpuGroups) != 0; // Save the processor group affinity of the initial thread