From 435b54ebbef5bb9a907dd11998a9babdc9421c4b Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 18 Feb 2020 17:27:07 +0100 Subject: [PATCH 1/3] Initialize Configuration#Concurrency from /sys/fs/cgroup/cpuset/cpuset.cpus refs #7842 --- icinga-app/icinga.cpp | 2 +- lib/base/configuration.cpp | 78 ++++++++++++++++++++++++++++++++++++++ lib/base/configuration.hpp | 1 + 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 1811c8e07..05b121054 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -440,7 +440,7 @@ static int Main() Configuration::SetReadOnly(true); if (!Configuration::ConcurrencyWasModified) { - Configuration::Concurrency = std::thread::hardware_concurrency(); + Configuration::Concurrency = Configuration::GetDefaultConcurrency(); } Application::GetTP().Restart(); diff --git a/lib/base/configuration.cpp b/lib/base/configuration.cpp index 908c16183..37b2f4569 100644 --- a/lib/base/configuration.cpp +++ b/lib/base/configuration.cpp @@ -3,6 +3,21 @@ #include "base/configuration.hpp" #include "base/configuration-ti.cpp" #include "base/exception.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +# include +# include +#endif /* __linux__ */ using namespace icinga; @@ -27,6 +42,69 @@ bool Configuration::AttachDebugger{false}; String Configuration::CacheDir; int Configuration::Concurrency{1}; bool Configuration::ConcurrencyWasModified{false}; + +int Configuration::GetDefaultConcurrency() +{ +#ifdef __linux__ + { + using namespace boost::algorithm; + using namespace boost::asio; + using namespace boost::system; + + int f = open("/sys/fs/cgroup/cpuset/cpuset.cpus", O_RDONLY); + + if (f < 0) { + if (errno != ENOENT) { + throw system_error(error_code(errno, system_category())); + } + } else { + std::string rawCpus; + + { + io_context io; + buffered_read_stream stream (io); + + stream.next_layer() = posix::stream_descriptor(io, f); + + try { + read(stream, dynamic_buffer(rawCpus)); + } catch (const system_error& se) { + if (se.code() != error::make_error_code(error::eof)) { + throw; + } + } + } + + rawCpus.erase(rawCpus.find_last_not_of('\n') + 1u); + + std::vector ranges; + boost::split(ranges, rawCpus, is_any_of(",")); + + std::set cpus; + + for (auto& range : ranges) { + std::vector rangeEnds; + boost::split(rangeEnds, range, is_any_of("-")); + + if (rangeEnds.size() > 1u) { + auto to (boost::lexical_cast(rangeEnds.at(1))); + + for (auto i (boost::lexical_cast(rangeEnds.at(0))); i <= to; ++i) { + cpus.emplace(i); + } + } else { + cpus.emplace(boost::lexical_cast(rangeEnds.at(0))); + } + } + + return cpus.size(); + } + } +#endif /* __linux__ */ + + return std::thread::hardware_concurrency(); +} + String Configuration::ConfigDir; String Configuration::DataDir; String Configuration::EventEngine; diff --git a/lib/base/configuration.hpp b/lib/base/configuration.hpp index a5aed01e8..de1280615 100644 --- a/lib/base/configuration.hpp +++ b/lib/base/configuration.hpp @@ -32,6 +32,7 @@ public: void SetCacheDir(const String& value, bool suppress_events = false, const Value& cookie = Empty) override; int GetConcurrency() const override; + static int GetDefaultConcurrency(); void SetConcurrency(int value, bool suppress_events = false, const Value& cookie = Empty) override; String GetConfigDir() const override; From 4c6bb2cea83db63cf044d1674672d6c58e5b6239 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Mon, 24 Aug 2020 13:32:50 +0200 Subject: [PATCH 2/3] Initialize Configuration#Concurrency also from /sys/fs/cgroup/cpu/cpu.cfs_quota_us refs #7842 --- lib/base/configuration.cpp | 87 +++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/lib/base/configuration.cpp b/lib/base/configuration.cpp index 37b2f4569..52718b5e9 100644 --- a/lib/base/configuration.cpp +++ b/lib/base/configuration.cpp @@ -4,10 +4,11 @@ #include "base/configuration-ti.cpp" #include "base/exception.hpp" #include -#include +#include +#include #include -#include -#include +#include +#include #include #include #include @@ -43,40 +44,46 @@ String Configuration::CacheDir; int Configuration::Concurrency{1}; bool Configuration::ConcurrencyWasModified{false}; +#ifdef __linux__ +static std::string ReadSysLine(const char *file) +{ + namespace io = boost::iostreams; + + std::string content; + io::stream stream; + int f = open(file, O_RDONLY); + + if (f < 0) { + if (errno == ENOENT) { + return ""; + } + + BOOST_THROW_EXCEPTION(posix_error() + << boost::errinfo_api_function("open") + << boost::errinfo_errno(errno) + << boost::errinfo_file_name(file)); + } + + stream.exceptions(decltype(stream)::failbit | decltype(stream)::badbit); + stream.open(io::file_descriptor(f, boost::iostreams::close_handle)); + stream.set_auto_close(true); + + std::getline(stream, content); + return content; +} +#endif /* __linux__ */ + int Configuration::GetDefaultConcurrency() { + using namespace boost::algorithm; + + auto concurrency (std::thread::hardware_concurrency()); + #ifdef __linux__ { - using namespace boost::algorithm; - using namespace boost::asio; - using namespace boost::system; - - int f = open("/sys/fs/cgroup/cpuset/cpuset.cpus", O_RDONLY); - - if (f < 0) { - if (errno != ENOENT) { - throw system_error(error_code(errno, system_category())); - } - } else { - std::string rawCpus; - - { - io_context io; - buffered_read_stream stream (io); - - stream.next_layer() = posix::stream_descriptor(io, f); - - try { - read(stream, dynamic_buffer(rawCpus)); - } catch (const system_error& se) { - if (se.code() != error::make_error_code(error::eof)) { - throw; - } - } - } - - rawCpus.erase(rawCpus.find_last_not_of('\n') + 1u); + auto rawCpus (ReadSysLine("/sys/fs/cgroup/cpuset/cpuset.cpus")); + if (rawCpus.length()) { std::vector ranges; boost::split(ranges, rawCpus, is_any_of(",")); @@ -97,12 +104,24 @@ int Configuration::GetDefaultConcurrency() } } - return cpus.size(); + concurrency = cpus.size(); + } + } + + { + auto cfsQuotaUs (ReadSysLine("/sys/fs/cgroup/cpu/cpu.cfs_quota_us")); + + if (cfsQuotaUs.length()) { + auto quota (boost::lexical_cast(cfsQuotaUs)); + + if (quota > 0) { + concurrency = std::min(std::max((decltype(concurrency))std::round(quota / 100000.0), 1u), concurrency); + } } } #endif /* __linux__ */ - return std::thread::hardware_concurrency(); + return concurrency; } String Configuration::ConfigDir; From dde5e35ee6e95d4772c8dd55ed22b78f55ec7e2f Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Fri, 27 Jan 2023 15:12:07 +0100 Subject: [PATCH 3/3] Initialize Configuration#Concurrency also from /sys/fs/cgroup/cpuset.cpus.effective --- lib/base/configuration.cpp | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/lib/base/configuration.cpp b/lib/base/configuration.cpp index 52718b5e9..fe67f45cb 100644 --- a/lib/base/configuration.cpp +++ b/lib/base/configuration.cpp @@ -81,30 +81,33 @@ int Configuration::GetDefaultConcurrency() #ifdef __linux__ { - auto rawCpus (ReadSysLine("/sys/fs/cgroup/cpuset/cpuset.cpus")); + for (auto* cpuset : {"/sys/fs/cgroup/cpuset.cpus.effective", "/sys/fs/cgroup/cpuset/cpuset.cpus"}) { + auto rawCpus (ReadSysLine(cpuset)); - if (rawCpus.length()) { - std::vector ranges; - boost::split(ranges, rawCpus, is_any_of(",")); + if (rawCpus.length()) { + std::vector ranges; + boost::split(ranges, rawCpus, is_any_of(",")); - std::set cpus; + std::set cpus; - for (auto& range : ranges) { - std::vector rangeEnds; - boost::split(rangeEnds, range, is_any_of("-")); + for (auto& range : ranges) { + std::vector rangeEnds; + boost::split(rangeEnds, range, is_any_of("-")); - if (rangeEnds.size() > 1u) { - auto to (boost::lexical_cast(rangeEnds.at(1))); + if (rangeEnds.size() > 1u) { + auto to (boost::lexical_cast(rangeEnds.at(1))); - for (auto i (boost::lexical_cast(rangeEnds.at(0))); i <= to; ++i) { - cpus.emplace(i); + for (auto i (boost::lexical_cast(rangeEnds.at(0))); i <= to; ++i) { + cpus.emplace(i); + } + } else { + cpus.emplace(boost::lexical_cast(rangeEnds.at(0))); } - } else { - cpus.emplace(boost::lexical_cast(rangeEnds.at(0))); } - } - concurrency = cpus.size(); + concurrency = cpus.size(); + break; + } } }