ClickHouse/src/Common/getNumberOfPhysicalCPUCores.cpp

75 lines
2.5 KiB
C++
Raw Normal View History

#include "getNumberOfPhysicalCPUCores.h"
2022-01-18 06:51:13 +00:00
#include <Common/config.h>
#if defined(OS_LINUX)
# include <cmath>
# include <fstream>
#endif
2019-01-28 13:16:08 +00:00
#if USE_CPUID
# include <libcpuid/libcpuid.h>
#endif
#include <thread>
#if defined(OS_LINUX)
2022-04-15 20:54:08 +00:00
static int readFrom(const char * filename, int default_value)
{
2022-04-15 20:54:08 +00:00
std::ifstream infile(filename);
if (!infile.is_open())
return default_value;
int idata;
if (infile >> idata)
return idata;
else
return default_value;
}
2022-04-15 20:54:08 +00:00
/// Try to look at cgroups limit if it is available.
static unsigned getCGroupLimitedCPUCores(unsigned default_cpu_count)
{
unsigned quota_count = default_cpu_count;
2022-04-15 20:54:08 +00:00
/// Return the number of milliseconds per period process is guaranteed to run.
/// -1 for no quota
int cgroup_quota = readFrom("/sys/fs/cgroup/cpu/cpu.cfs_quota_us", -1);
int cgroup_period = readFrom("/sys/fs/cgroup/cpu/cpu.cfs_period_us", -1);
if (cgroup_quota > -1 && cgroup_period > 0)
quota_count = ceil(static_cast<float>(cgroup_quota) / static_cast<float>(cgroup_period));
return std::min(default_cpu_count, quota_count);
}
2022-04-15 20:54:08 +00:00
#endif
unsigned getNumberOfPhysicalCPUCores()
{
2022-04-15 20:54:08 +00:00
unsigned cpu_count = 0; // start with an invalid num
2022-04-15 20:54:08 +00:00
#if USE_CPUID
cpu_raw_data_t raw_data;
cpu_id_t data;
2022-04-15 20:54:08 +00:00
/// On Xen VMs, libcpuid returns wrong info (zero number of cores). Fallback to alternative method.
/// Also, libcpuid does not support some CPUs like AMD Hygon C86 7151.
/// Also, libcpuid gives strange result on Google Compute Engine VMs.
/// Example:
/// num_cores = 12, /// number of physical cores on current CPU socket
/// total_logical_cpus = 1, /// total number of logical cores on all sockets
/// num_logical_cpus = 24. /// number of logical cores on current CPU socket
/// It means two-way hyper-threading (24 / 12), but contradictory, 'total_logical_cpus' == 1.
2022-04-15 20:54:08 +00:00
if (0 == cpuid_get_raw_data(&raw_data) && 0 == cpu_identify(&raw_data, &data) && data.num_logical_cpus != 0)
cpu_count = data.num_cores * data.total_logical_cpus / data.num_logical_cpus;
#endif
2022-04-15 20:54:08 +00:00
/// As a fallback (also for non-x86 architectures) assume there are no hyper-threading on the system.
/// (Actually, only Aarch64 is supported).
if (cpu_count == 0)
cpu_count = std::thread::hardware_concurrency();
#if defined(OS_LINUX)
2022-04-15 20:54:08 +00:00
/// TODO: add a setting for disabling that, similar to UseContainerSupport in java
cpu_count = getCGroupLimitedCPUCores(cpu_count);
#endif
return cpu_count;
}