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-11-29 21:37:47 +0000 |
commit | e88f9219666b223ee6f5fc621d2a0abdf44f392a (patch) | |
tree | 95a1a11c6f0256893129cdd88d7400180b1a3464 /src/mongo | |
parent | 04ccacc3fc835d99bd53c0b9beaa9f99f4622b3e (diff) | |
download | mongo-e88f9219666b223ee6f5fc621d2a0abdf44f392a.tar.gz |
SERVER-67704 SERVER-67705 Fix processor package counting for ARM
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/commands/generic_servers.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/commands/generic_servers.idl | 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 | 54 | ||||
-rw-r--r-- | src/mongo/util/processinfo_unknown.cpp | 4 | ||||
-rw-r--r-- | src/mongo/util/processinfo_windows.cpp | 45 |
10 files changed, 145 insertions, 106 deletions
diff --git a/src/mongo/db/commands/generic_servers.cpp b/src/mongo/db/commands/generic_servers.cpp index af1ffc8d110..46276bb285b 100644 --- a/src/mongo/db/commands/generic_servers.cpp +++ b/src/mongo/db/commands/generic_servers.cpp @@ -158,8 +158,11 @@ HostInfoReply HostInfoCmd::Invocation::typedRun(OperationContext*) { system.setMemSizeMB(static_cast<long>(p.getSystemMemSizeMB())); system.setMemLimitMB(static_cast<long>(p.getMemSizeMB())); system.setNumCores(static_cast<int>(p.getNumAvailableCores())); + system.setNumPhysicalCores(static_cast<int>(p.getNumPhysicalCores())); + system.setNumCpuSockets(static_cast<int>(p.getNumCpuSockets())); system.setCpuArch(p.getArch()); system.setNumaEnabled(p.hasNumaEnabled()); + system.setNumNumaNodes(static_cast<int>(p.getNumNumaNodes())); HostInfoOsReply os; os.setType(p.getOsType()); diff --git a/src/mongo/db/commands/generic_servers.idl b/src/mongo/db/commands/generic_servers.idl index 4e6f08ab71f..33b54dc4651 100644 --- a/src/mongo/db/commands/generic_servers.idl +++ b/src/mongo/db/commands/generic_servers.idl @@ -65,8 +65,11 @@ structs: memSizeMB: long memLimitMB: long numCores: int + numPhysicalCores: int + numCpuSockets: int cpuArch: string numaEnabled: bool + numNumaNodes: int hostInfoOsReply: description: "hostInfo.os reply fields" diff --git a/src/mongo/util/processinfo.h b/src/mongo/util/processinfo.h index 3046f809e4f..509a9d5ccf1 100644 --- a/src/mongo/util/processinfo.h +++ b/src/mongo/util/processinfo.h @@ -113,6 +113,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. */ @@ -142,6 +149,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() { @@ -180,9 +197,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. @@ -198,8 +217,10 @@ private: memLimit(0), numCores(0), numPhysicalCores(0), + numCpuSockets(0), pageSize(0), hasNuma(false), + numNumaNodes(0), preferMsyncOverFSync(true) { // populate SystemInfo during construction collectSystemInfo(); @@ -230,8 +251,6 @@ private: ProcessId _pid; - static bool checkNumaEnabled(); - 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 b57e9ff6c1a..66709cbfe57 100644 --- a/src/mongo/util/processinfo_freebsd.cpp +++ b/src/mongo/util/processinfo_freebsd.cpp @@ -94,10 +94,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; @@ -166,7 +162,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 c0d4454ad64..6f762f8c580 100644 --- a/src/mongo/util/processinfo_linux.cpp +++ b/src/mongo/util/processinfo_linux.cpp @@ -427,6 +427,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) { @@ -674,6 +692,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() { @@ -682,10 +738,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) { @@ -702,9 +760,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")); @@ -729,44 +790,10 @@ 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; -} - } // namespace mongo diff --git a/src/mongo/util/processinfo_openbsd.cpp b/src/mongo/util/processinfo_openbsd.cpp index 09ef930501a..ab7773ab4b1 100644 --- a/src/mongo/util/processinfo_openbsd.cpp +++ b/src/mongo/util/processinfo_openbsd.cpp @@ -98,10 +98,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; @@ -183,7 +179,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 f3eb932cd86..662b26dcfd3 100644 --- a/src/mongo/util/processinfo_osx.cpp +++ b/src/mongo/util/processinfo_osx.cpp @@ -184,9 +184,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")); @@ -196,16 +198,10 @@ 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("cpuString", getSysctlByName<std::string>("machdep.cpu.brand_string")); bExtra.append("pageSize", static_cast<int>(getSysctlByName<NumberVal>("hw.pagesize"))); bExtra.append("scheduler", getSysctlByName<std::string>("kern.sched")); _extraStats = bExtra.obj(); } -bool ProcessInfo::checkNumaEnabled() { - return false; -} - } // namespace mongo diff --git a/src/mongo/util/processinfo_solaris.cpp b/src/mongo/util/processinfo_solaris.cpp index de64cf46998..ba66d31d709 100644 --- a/src/mongo/util/processinfo_solaris.cpp +++ b/src/mongo/util/processinfo_solaris.cpp @@ -134,6 +134,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 */ @@ -203,31 +230,4 @@ void ProcessInfo::SystemInfo::collectSystemInfo() { _extraStats = bExtra.obj(); } -bool ProcessInfo::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; -} - } // namespace mongo diff --git a/src/mongo/util/processinfo_unknown.cpp b/src/mongo/util/processinfo_unknown.cpp index 1011c4dbfef..c57516eaeac 100644 --- a/src/mongo/util/processinfo_unknown.cpp +++ b/src/mongo/util/processinfo_unknown.cpp @@ -51,10 +51,6 @@ int ProcessInfo::getResidentSize() { return -1; } -bool ProcessInfo::checkNumaEnabled() { - return false; -} - void ProcessInfo::SystemInfo::collectSystemInfo() {} void ProcessInfo::getExtraInfo(BSONObjBuilder& info) {} diff --git a/src/mongo/util/processinfo_windows.cpp b/src/mongo/util/processinfo_windows.cpp index 3f4e5ba74f1..d90d0898b6c 100644 --- a/src/mongo/util/processinfo_windows.cpp +++ b/src/mongo/util/processinfo_windows.cpp @@ -93,13 +93,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 @@ -247,10 +261,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); @@ -354,21 +371,7 @@ 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; -} - } // namespace mongo |