diff options
author | Gabriel Marks <gabriel.marks@mongodb.com> | 2022-11-29 20:38:00 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-12-06 19:23:25 +0000 |
commit | ca53263a7b6caa8f1596725ce49aff47266ff941 (patch) | |
tree | bd09d529a8d7582768ca2dc4463151050960d710 | |
parent | 41f398a4686bbc0b1d53d019efcb80760a18bbd2 (diff) | |
download | mongo-ca53263a7b6caa8f1596725ce49aff47266ff941.tar.gz |
SERVER-67704 SERVER-67705 Fix processor package counting for ARM
-rw-r--r-- | jstests/core/hostinfo.js | 8 | ||||
-rw-r--r-- | src/mongo/db/commands/generic_servers.cpp | 3 | ||||
-rw-r--r-- | src/mongo/util/processinfo.h | 23 | ||||
-rw-r--r-- | src/mongo/util/processinfo_freebsd.cpp | 6 | ||||
-rw-r--r-- | src/mongo/util/processinfo_linux.cpp | 97 | ||||
-rw-r--r-- | src/mongo/util/processinfo_openbsd.cpp | 6 | ||||
-rw-r--r-- | src/mongo/util/processinfo_osx.cpp | 10 | ||||
-rw-r--r-- | src/mongo/util/processinfo_solaris.cpp | 52 | ||||
-rw-r--r-- | src/mongo/util/processinfo_unknown.cpp | 4 | ||||
-rw-r--r-- | src/mongo/util/processinfo_windows.cpp | 45 |
10 files changed, 148 insertions, 106 deletions
diff --git a/jstests/core/hostinfo.js b/jstests/core/hostinfo.js index c088e52b853..c32daf809f4 100644 --- a/jstests/core/hostinfo.js +++ b/jstests/core/hostinfo.js @@ -13,11 +13,15 @@ function commonOSAsserts(hostinfo) { } function coresAsserts(hostinfo) { - assert.gt(hostinfo.extra.physicalCores, 0, "Missing " + hostinfo.os.type + " physical cores"); + assert.gt( + hostinfo.system.numPhysicalCores, 0, "Missing " + hostinfo.os.type + " physical cores"); assert.gt(hostinfo.system.numCores, 0, "Missing " + hostinfo.os.type + " logical cores"); - assert.lte(hostinfo.extra.physicalCores, + assert.lte(hostinfo.system.numPhysicalCores, hostinfo.system.numCores, hostinfo.os.type + " physical cores not larger then logical cores"); + + assert.gt(hostinfo.system.numCpuSockets, 0, "Missing " + hostinfo.os.type + " Sockets"); + assert.gt(hostinfo.system.numNumaNodes, 0, "Missing " + hostinfo.os.type + " NUMA Nodes"); } assert.commandWorked(db.hostInfo()); diff --git a/src/mongo/db/commands/generic_servers.cpp b/src/mongo/db/commands/generic_servers.cpp index cde9a61764c..88f4d2cb076 100644 --- a/src/mongo/db/commands/generic_servers.cpp +++ b/src/mongo/db/commands/generic_servers.cpp @@ -130,8 +130,11 @@ public: bSys.append("memSizeMB", static_cast<long long>(p.getSystemMemSizeMB())); bSys.append("memLimitMB", static_cast<long long>(p.getMemSizeMB())); bSys.append("numCores", static_cast<int>(p.getNumAvailableCores())); + bSys.append("numPhysicalCores", static_cast<int>(p.getNumPhysicalCores())); + bSys.append("numCpuSockets", static_cast<int>(p.getNumCpuSockets())); bSys.append("cpuArch", p.getArch()); bSys.append("numaEnabled", p.hasNumaEnabled()); + bSys.append("numNumaNodes", static_cast<int>(p.getNumNumaNodes())); bOs.append("type", p.getOsType()); bOs.append("name", p.getOsName()); bOs.append("version", p.getOsVersion()); diff --git a/src/mongo/util/processinfo.h b/src/mongo/util/processinfo.h index 416599a17c7..184e6c27e66 100644 --- a/src/mongo/util/processinfo.h +++ b/src/mongo/util/processinfo.h @@ -112,6 +112,13 @@ public: } /** + * Get the number of CPU sockets + */ + static unsigned getNumCpuSockets() { + return sysInfo().numCpuSockets; + } + + /** * Get the number of cores available. Make a best effort to get the cores for this process. * If that information is not available, get the total number of CPUs. */ @@ -141,6 +148,16 @@ public: } /** + * Get the number of NUMA nodes if NUMA is enabled, or 1 otherwise. + */ + static unsigned long getNumNumaNodes() { + if (sysInfo().hasNuma) { + return sysInfo().numNumaNodes; + } + return 1; + } + + /** * Determine if we need to workaround slow msync performance on Illumos/Solaris */ static bool preferMsyncOverFSync() { @@ -206,9 +223,11 @@ private: unsigned long long memLimit; unsigned numCores; unsigned numPhysicalCores; + unsigned numCpuSockets; unsigned long long pageSize; std::string cpuArch; bool hasNuma; + unsigned numNumaNodes; BSONObj _extraStats; // On non-Solaris (ie, Linux, Darwin, *BSD) kernels, prefer msync. @@ -224,8 +243,10 @@ private: memLimit(0), numCores(0), numPhysicalCores(0), + numCpuSockets(0), pageSize(0), hasNuma(false), + numNumaNodes(0), preferMsyncOverFSync(true) { // populate SystemInfo during construction collectSystemInfo(); @@ -238,8 +259,6 @@ private: ProcessId _pid; - static bool checkNumaEnabled(); - inline static const SystemInfo& sysInfo() { static ProcessInfo::SystemInfo systemInfo; return systemInfo; diff --git a/src/mongo/util/processinfo_freebsd.cpp b/src/mongo/util/processinfo_freebsd.cpp index d7f1d4127ca..851aae9ec0d 100644 --- a/src/mongo/util/processinfo_freebsd.cpp +++ b/src/mongo/util/processinfo_freebsd.cpp @@ -92,10 +92,6 @@ int getSysctlByNameWithDefault<std::string>(const char* sysctlName, return 0; } -bool ProcessInfo::checkNumaEnabled() { - return false; -} - int ProcessInfo::getVirtualMemorySize() { kvm_t* kd = NULL; int cnt = 0; @@ -168,7 +164,7 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { pageSize = static_cast<unsigned long long>(sysconf(_SC_PAGESIZE)); - hasNuma = checkNumaEnabled(); + hasNuma = false; } void ProcessInfo::getExtraInfo(BSONObjBuilder& info) {} diff --git a/src/mongo/util/processinfo_linux.cpp b/src/mongo/util/processinfo_linux.cpp index 6460a892d38..9063f140988 100644 --- a/src/mongo/util/processinfo_linux.cpp +++ b/src/mongo/util/processinfo_linux.cpp @@ -407,6 +407,24 @@ public: } /** + * count the number of processor packages + */ + static int getNumCpuSockets() { + std::set<std::string> socketIds; + + CpuInfoParser cpuInfoParser{ + { + {"physical id", [&](const std::string& value) { socketIds.insert(value); }}, + }, + []() {}}; + cpuInfoParser.run(); + + // On ARM64, the "physical id" field is unpopulated, causing there to be 0 sockets found. In + // this case, we default to 1. + return std::max(socketIds.size(), 1ul); + } + + /** * Get some details about the CPU */ static void getCpuInfo(int& procCount, std::string& freq, std::string& features) { @@ -653,6 +671,44 @@ void ProcessInfo::getExtraInfo(BSONObjBuilder& info) { } /** + * If the process is running with (cc)NUMA enabled, return the number of NUMA nodes. Else, return 0. + */ +unsigned long countNumaNodes() { + bool hasMultipleNodes = false; + bool hasNumaMaps = false; + + try { + hasMultipleNodes = boost::filesystem::exists("/sys/devices/system/node/node1"); + hasNumaMaps = boost::filesystem::exists("/proc/self/numa_maps"); + + if (hasMultipleNodes && hasNumaMaps) { + // proc is populated with numa entries + + // read the second column of first line to determine numa state + // ('default' = enabled, 'interleave' = disabled). Logic from version.cpp's warnings. + std::string line = + LinuxSysHelper::readLineFromFile("/proc/self/numa_maps").append(" \0"); + size_t pos = line.find(' '); + if (pos != std::string::npos && + line.substr(pos + 1, 10).find("interleave") == std::string::npos) { + // interleave not found, count NUMA nodes by finding the highest numbered node file + unsigned long i = 2; + while (boost::filesystem::exists( + std::string(str::stream() << "/sys/devices/system/node/node" << i++))) + ; + return i; + } + } + } catch (boost::filesystem::filesystem_error& e) { + LOGV2(23340, + "WARNING: Cannot detect if NUMA interleaving is enabled. Failed to probe", + "path"_attr = e.path1().string(), + "reason"_attr = e.code().message()); + } + return 0; +} + +/** * Save a BSON obj representing the host system's details */ void ProcessInfo::SystemInfo::collectSystemInfo() { @@ -661,10 +717,12 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { std::string cpuFreq, cpuFeatures; int cpuCount; int physicalCores; + int cpuSockets; std::string verSig = LinuxSysHelper::readLineFromFile("/proc/version_signature"); LinuxSysHelper::getCpuInfo(cpuCount, cpuFreq, cpuFeatures); LinuxSysHelper::getNumPhysicalCores(physicalCores); + cpuSockets = LinuxSysHelper::getNumCpuSockets(); LinuxSysHelper::getLinuxDistro(distroName, distroVersion); if (uname(&unameData) == -1) { @@ -681,9 +739,12 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { memLimit = LinuxSysHelper::getMemorySizeLimit(); addrSize = sizeof(void*) * CHAR_BIT; numCores = cpuCount; + numPhysicalCores = physicalCores; + numCpuSockets = cpuSockets; pageSize = static_cast<unsigned long long>(sysconf(_SC_PAGESIZE)); cpuArch = unameData.machine; - hasNuma = checkNumaEnabled(); + numNumaNodes = countNumaNodes(); + hasNuma = numNumaNodes; BSONObjBuilder bExtra; bExtra.append("versionString", LinuxSysHelper::readLineFromFile("/proc/version")); @@ -708,46 +769,12 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { bExtra.append("pageSize", static_cast<long long>(pageSize)); bExtra.append("numPages", static_cast<int>(sysconf(_SC_PHYS_PAGES))); bExtra.append("maxOpenFiles", static_cast<int>(sysconf(_SC_OPEN_MAX))); - bExtra.append("physicalCores", physicalCores); appendMountInfo(bExtra); _extraStats = bExtra.obj(); } -/** - * Determine if the process is running with (cc)NUMA - */ -bool ProcessInfo::checkNumaEnabled() { - bool hasMultipleNodes = false; - bool hasNumaMaps = false; - - try { - hasMultipleNodes = boost::filesystem::exists("/sys/devices/system/node/node1"); - hasNumaMaps = boost::filesystem::exists("/proc/self/numa_maps"); - } catch (boost::filesystem::filesystem_error& e) { - LOGV2(23340, - "WARNING: Cannot detect if NUMA interleaving is enabled. Failed to probe", - "path"_attr = e.path1().string(), - "reason"_attr = e.code().message()); - return false; - } - - if (hasMultipleNodes && hasNumaMaps) { - // proc is populated with numa entries - - // read the second column of first line to determine numa state - // ('default' = enabled, 'interleave' = disabled). Logic from version.cpp's warnings. - std::string line = LinuxSysHelper::readLineFromFile("/proc/self/numa_maps").append(" \0"); - size_t pos = line.find(' '); - if (pos != std::string::npos && - line.substr(pos + 1, 10).find("interleave") == std::string::npos) - // interleave not found; - return true; - } - return false; -} - bool ProcessInfo::blockCheckSupported() { return true; } diff --git a/src/mongo/util/processinfo_openbsd.cpp b/src/mongo/util/processinfo_openbsd.cpp index 5736504ce9c..74fff99d7e1 100644 --- a/src/mongo/util/processinfo_openbsd.cpp +++ b/src/mongo/util/processinfo_openbsd.cpp @@ -96,10 +96,6 @@ int getSysctlByIDWithDefault<std::string>(const int* sysctlID, return 0; } -bool ProcessInfo::checkNumaEnabled() { - return false; -} - int ProcessInfo::getVirtualMemorySize() { kvm_t* kd = NULL; int cnt = 0; @@ -185,7 +181,7 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { pageSize = static_cast<unsigned long long>(sysconf(_SC_PAGESIZE)); - hasNuma = checkNumaEnabled(); + hasNuma = false; } void ProcessInfo::getExtraInfo(BSONObjBuilder& info) {} diff --git a/src/mongo/util/processinfo_osx.cpp b/src/mongo/util/processinfo_osx.cpp index 0a525ffa234..1dd24421a79 100644 --- a/src/mongo/util/processinfo_osx.cpp +++ b/src/mongo/util/processinfo_osx.cpp @@ -190,9 +190,11 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { memSize = getSysctlByName<NumberVal>("hw.memsize"); memLimit = memSize; numCores = getSysctlByName<NumberVal>("hw.ncpu"); // includes hyperthreading cores + numPhysicalCores = getSysctlByName<NumberVal>("machdep.cpu.core_count"); + numCpuSockets = getSysctlByName<NumberVal>("hw.packages"); pageSize = static_cast<unsigned long long>(sysconf(_SC_PAGESIZE)); cpuArch = getSysctlByName<std::string>("hw.machine"); - hasNuma = checkNumaEnabled(); + hasNuma = false; BSONObjBuilder bExtra; bExtra.append("versionString", getSysctlByName<std::string>("kern.version")); @@ -202,8 +204,6 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { "nfsAsync", static_cast<int>(getSysctlByName<NumberVal>("vfs.generic.nfs.client.allow_async"))); bExtra.append("model", getSysctlByName<std::string>("hw.model")); - bExtra.append("physicalCores", - static_cast<int>(getSysctlByName<NumberVal>("machdep.cpu.core_count"))); bExtra.append( "cpuFrequencyMHz", static_cast<int>((getSysctlByName<NumberVal>("hw.cpufrequency") / (1000 * 1000)))); @@ -214,10 +214,6 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { _extraStats = bExtra.obj(); } -bool ProcessInfo::checkNumaEnabled() { - return false; -} - bool ProcessInfo::blockCheckSupported() { return true; } diff --git a/src/mongo/util/processinfo_solaris.cpp b/src/mongo/util/processinfo_solaris.cpp index 54ae6184fe2..aba4f0f6854 100644 --- a/src/mongo/util/processinfo_solaris.cpp +++ b/src/mongo/util/processinfo_solaris.cpp @@ -133,6 +133,33 @@ void ProcessInfo::getExtraInfo(BSONObjBuilder& info) { info.appendNumber("page_faults", static_cast<long long>(p.prusage.pr_majf)); } +bool checkNumaEnabled() { + lgrp_cookie_t cookie = lgrp_init(LGRP_VIEW_OS); + + if (cookie == LGRP_COOKIE_NONE) { + auto ec = lastSystemError(); + LOGV2_WARNING(23362, + "lgrp_init failed: {errnoWithDescription}", + "errnoWithDescription"_attr = errorMessage(ec)); + return false; + } + + ON_BLOCK_EXIT([&] { lgrp_fini(cookie); }); + + int groups = lgrp_nlgrps(cookie); + + if (groups == -1) { + auto ec = lastSystemError(); + LOGV2_WARNING(23363, + "lgrp_nlgrps failed: {errnoWithDescription}", + "errnoWithDescription"_attr = errorMessage(ec)); + return false; + } + + // NUMA machines have more then 1 locality group + return groups > 1; +} + /** * Save a BSON obj representing the host system's details */ @@ -202,31 +229,6 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { _extraStats = bExtra.obj(); } -bool ProcessInfo::checkNumaEnabled() { - lgrp_cookie_t cookie = lgrp_init(LGRP_VIEW_OS); - - if (cookie == LGRP_COOKIE_NONE) { - LOGV2_WARNING(23362, - "lgrp_init failed: {errnoWithDescription}", - "errnoWithDescription"_attr = errnoWithDescription()); - return false; - } - - ON_BLOCK_EXIT([&] { lgrp_fini(cookie); }); - - int groups = lgrp_nlgrps(cookie); - - if (groups == -1) { - LOGV2_WARNING(23363, - "lgrp_nlgrps failed: {errnoWithDescription}", - "errnoWithDescription"_attr = errnoWithDescription()); - return false; - } - - // NUMA machines have more then 1 locality group - return groups > 1; -} - bool ProcessInfo::blockCheckSupported() { return true; } diff --git a/src/mongo/util/processinfo_unknown.cpp b/src/mongo/util/processinfo_unknown.cpp index 05f84b7f22c..379fc777f40 100644 --- a/src/mongo/util/processinfo_unknown.cpp +++ b/src/mongo/util/processinfo_unknown.cpp @@ -55,10 +55,6 @@ double ProcessInfo::getSystemMemoryPressurePercentage() { return 0.0; } -bool ProcessInfo::checkNumaEnabled() { - return false; -} - bool ProcessInfo::blockCheckSupported() { return false; } diff --git a/src/mongo/util/processinfo_windows.cpp b/src/mongo/util/processinfo_windows.cpp index e005c76614a..0ff073a0494 100644 --- a/src/mongo/util/processinfo_windows.cpp +++ b/src/mongo/util/processinfo_windows.cpp @@ -91,13 +91,27 @@ LpiRecords getLogicalProcessorInformationRecords() { return lpiRecords; } -int getPhysicalCores() { - int processorCoreCount = 0; +struct ParsedProcessorInfo { + int physicalCoreCount; + int numaNodeCount; + int processorPackageCount; +}; + +ParsedProcessorInfo getProcessorInfo() { + ParsedProcessorInfo ppi{0, 0, 0}; for (auto&& lpi : getLogicalProcessorInformationRecords()) { - if (lpi.Relationship == RelationProcessorCore) - processorCoreCount++; + switch (lpi.Relationship) { + case RelationProcessorCore: + ppi.physicalCoreCount++; + break; + case RelationNumaNode: + ppi.numaNodeCount++; + break; + case RelationProcessorPackage: + ppi.processorPackageCount++; + } } - return processorCoreCount; + return ppi; } } // namespace @@ -284,10 +298,13 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { GetNativeSystemInfo(&ntsysinfo); addrSize = (ntsysinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ? 64 : 32); numCores = ntsysinfo.dwNumberOfProcessors; - numPhysicalCores = getPhysicalCores(); + auto ppi = getProcessorInfo(); + numPhysicalCores = ppi.physicalCoreCount; + numCpuSockets = ppi.processorPackageCount; + hasNuma = ppi.numaNodeCount > 1; + numNumaNodes = ppi.numaNodeCount; pageSize = static_cast<unsigned long long>(ntsysinfo.dwPageSize); bExtra.append("pageSize", static_cast<long long>(pageSize)); - bExtra.append("physicalCores", static_cast<int>(numPhysicalCores)); // get memory info mse.dwLength = sizeof(mse); @@ -391,23 +408,9 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { osType = "Windows"; osVersion = verstr.str(); - hasNuma = checkNumaEnabled(); _extraStats = bExtra.obj(); } - -bool ProcessInfo::checkNumaEnabled() { - DWORD numaNodeCount = 0; - for (auto&& lpi : getLogicalProcessorInformationRecords()) { - if (lpi.Relationship == RelationNumaNode) - // Non-NUMA systems report a single record of this type. - ++numaNodeCount; - } - - // For non-NUMA machines, the count is 1 - return numaNodeCount > 1; -} - bool ProcessInfo::blockCheckSupported() { return true; } |