diff --git a/builds/install/misc/firebird.conf b/builds/install/misc/firebird.conf index 98959d4b8dd..eb80895a9a3 100644 --- a/builds/install/misc/firebird.conf +++ b/builds/install/misc/firebird.conf @@ -1005,6 +1005,12 @@ # CPU 1 and CPU 2, the value is 3. To use CPU 2 and CPU 3, the value # is 6. The default value is 0 - no affinity will be set. # +# About systems with heterogeneous (Efficient\Performance) set of cores: +# on Windows 10 and later, if affinity is not set nor by CpuAffinityMask, +# nor by the caller process, then server tries to exclude efficient cores +# from own affinity mask. I.e. default affinity mask includes performance +# cores only. +# # Type: integer # #CpuAffinityMask = 0 diff --git a/src/common/os/os_utils.h b/src/common/os/os_utils.h index 3288e1e971f..bbdc2f1c459 100644 --- a/src/common/os/os_utils.h +++ b/src/common/os/os_utils.h @@ -358,6 +358,10 @@ namespace os_utils #endif // WIN_NT +#ifdef WIN_NT + void setDefaultAffinity(); +#endif + class CtrlCHandler { public: diff --git a/src/common/os/win32/os_utils.cpp b/src/common/os/win32/os_utils.cpp index 85d7c1e1181..15fb64f1b8b 100644 --- a/src/common/os/win32/os_utils.cpp +++ b/src/common/os/win32/os_utils.cpp @@ -29,6 +29,7 @@ #include "../common/classes/array.h" #include "../common/classes/init.h" +#include "../common/classes/GenericMap.h" #include "../common/gdsassert.h" #include "../common/os/guid.h" #include "../common/os/os_utils.h" @@ -560,6 +561,65 @@ void getUniqueFileId(HANDLE fd, UCharBuffer& id) sizeof(file_info.nFileIndexLow)); } +void setDefaultAffinity() +{ + HANDLE hCurrProc = GetCurrentProcess(); + + DWORD_PTR procMask, sysMask, newMask; + GetProcessAffinityMask(hCurrProc, &procMask, &sysMask); + + // Don't change affinity if it was set by caller process + if (procMask != sysMask) + return; + + newMask = sysMask; + + DWORD len = 0; + + if (!GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, &len)) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return; + } + + HalfStaticArray buff; + auto p = buff.getBuffer(len); + auto const end = p + len; + auto pSLPI = reinterpret_cast(p); + + if (!GetLogicalProcessorInformationEx(RelationProcessorCore, pSLPI, &len)) + return; + + // Efficiency Class to Cores map + GenericMap> effClassMasks; + + while (p < end) + { + if (pSLPI->Relationship == RelationProcessorCore) + { + DWORD_PTR coreMask = 0; + for (size_t i = 0; i < pSLPI->Processor.GroupCount; i++) + coreMask |= pSLPI->Processor.GroupMask[i].Mask; + + DWORD_PTR* pMask = effClassMasks.get(pSLPI->Processor.EfficiencyClass); + if (!pMask) + effClassMasks.put(pSLPI->Processor.EfficiencyClass, coreMask); + else + *pMask |= coreMask; + } + + p += pSLPI->Size; + pSLPI = reinterpret_cast(p); + } + + // Exclude efficient cores, i.e. cores with lowest efficient class + if (effClassMasks.count() > 1) + newMask &= ~(*effClassMasks.begin()).second; + + if (newMask && newMask != procMask) + SetProcessAffinityMask(hCurrProc, newMask); +} + /// class CtrlCHandler diff --git a/src/remote/server/os/win32/srvr_w32.cpp b/src/remote/server/os/win32/srvr_w32.cpp index be7a705cdd3..93ae0925beb 100644 --- a/src/remote/server/os/win32/srvr_w32.cpp +++ b/src/remote/server/os/win32/srvr_w32.cpp @@ -219,6 +219,8 @@ int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs, const DWORD_PTR affinity = Config::getCpuAffinityMask(); if (affinity) SetProcessAffinityMask(GetCurrentProcess(), affinity); + else + os_utils::setDefaultAffinity(); protocol_inet[0] = 0;