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 21:14:51 +0000
commit01d06e110ce176b3e803352d470c91e1abcc36d5 (patch)
tree898ef8c80b0d5009e2c572e8f0052f80d4e45564
parent3a55839246c3667ad7ebb2726f56d2098ac88971 (diff)
downloadmongo-01d06e110ce176b3e803352d470c91e1abcc36d5.tar.gz
SERVER-67704 SERVER-67705 Fix processor package counting for ARM
-rw-r--r--jstests/core/hostinfo.js4
-rw-r--r--src/mongo/db/commands/generic_servers.cpp3
-rw-r--r--src/mongo/db/commands/generic_servers.idl3
-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
11 files changed, 149 insertions, 104 deletions
diff --git a/jstests/core/hostinfo.js b/jstests/core/hostinfo.js
index 04f341a659d..c3a0f34994a 100644
--- a/jstests/core/hostinfo.js
+++ b/jstests/core/hostinfo.js
@@ -35,8 +35,12 @@ if (hostinfo.os.type != "") {
assert.neq(hostinfo.system.cpuAddrSize, "" || null || 0, "Missing CPU Address Size");
assert.neq(hostinfo.system.memSizeMB, "" || null, "Missing Memory Size");
assert.neq(hostinfo.system.numCores, "" || null || 0, "Missing Number of Cores");
+ assert.neq(
+ hostinfo.system.numPhysicalCores, "" || null || 0, "Missing Number of Physical Cores");
+ assert.neq(hostinfo.system.numCpuSockets, "" || null || 0, "Missing Number of CPU Sockets");
assert.neq(hostinfo.system.cpuArch, "" || null, "Missing CPU Architecture");
assert.neq(hostinfo.system.numaEnabled, "" || null, "Missing NUMA flag");
+ assert.neq(hostinfo.system.numNumaNodes, "" || null || 0, "Missing Number of NUMA Nodes");
}
var buildInfo = assert.commandWorked(db.runCommand({buildInfo: 1}));
diff --git a/src/mongo/db/commands/generic_servers.cpp b/src/mongo/db/commands/generic_servers.cpp
index 41448e90dde..7a6b87c13fe 100644
--- a/src/mongo/db/commands/generic_servers.cpp
+++ b/src/mongo/db/commands/generic_servers.cpp
@@ -156,8 +156,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 598ce277333..c1f626a7f07 100644
--- a/src/mongo/db/commands/generic_servers.idl
+++ b/src/mongo/db/commands/generic_servers.idl
@@ -64,8 +64,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 942ffc54136..361276d5bf3 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 d13b0295e92..fbd49a6d4b9 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;
@@ -164,7 +160,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 37e3d2ea3fc..0737ed3aa52 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) {
@@ -649,6 +667,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() {
@@ -657,10 +713,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) {
@@ -677,9 +735,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"));
@@ -704,44 +765,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 40ad2fc1a70..071b26b8521 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;
@@ -181,7 +177,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 cb42b570513..0cd0cbb4cf6 100644
--- a/src/mongo/util/processinfo_osx.cpp
+++ b/src/mongo/util/processinfo_osx.cpp
@@ -182,9 +182,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"));
@@ -194,8 +196,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))));
@@ -206,8 +206,4 @@ void ProcessInfo::SystemInfo::collectSystemInfo() {
_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 95598132526..10f97f9406d 100644
--- a/src/mongo/util/processinfo_solaris.cpp
+++ b/src/mongo/util/processinfo_solaris.cpp
@@ -129,6 +129,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
*/
@@ -198,29 +225,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) {
- 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;
-}
-
} // 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 5cf7edbdee2..51068027b51 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
@@ -245,10 +259,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);
@@ -352,21 +369,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