summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Marks <gabriel.marks@mongodb.com>2022-11-29 20:38:00 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-12-06 19:23:25 +0000
commitca53263a7b6caa8f1596725ce49aff47266ff941 (patch)
treebd09d529a8d7582768ca2dc4463151050960d710
parent41f398a4686bbc0b1d53d019efcb80760a18bbd2 (diff)
downloadmongo-ca53263a7b6caa8f1596725ce49aff47266ff941.tar.gz
SERVER-67704 SERVER-67705 Fix processor package counting for ARM
-rw-r--r--jstests/core/hostinfo.js8
-rw-r--r--src/mongo/db/commands/generic_servers.cpp3
-rw-r--r--src/mongo/util/processinfo.h23
-rw-r--r--src/mongo/util/processinfo_freebsd.cpp6
-rw-r--r--src/mongo/util/processinfo_linux.cpp97
-rw-r--r--src/mongo/util/processinfo_openbsd.cpp6
-rw-r--r--src/mongo/util/processinfo_osx.cpp10
-rw-r--r--src/mongo/util/processinfo_solaris.cpp52
-rw-r--r--src/mongo/util/processinfo_unknown.cpp4
-rw-r--r--src/mongo/util/processinfo_windows.cpp45
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;
}