From f590cf58fb9f2b0899354402213087832610bf87 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 18 Jul 2019 19:11:45 +0700 Subject: [PATCH] Added support for threads restart if config changed. --- src/backend/common/Workers.cpp | 13 ++--- src/backend/common/Workers.h | 3 +- src/backend/common/interfaces/IBackend.h | 16 +++--- src/backend/cpu/CpuBackend.cpp | 73 ++++++++++-------------- src/backend/cpu/CpuBackend.h | 1 + src/backend/cpu/CpuConfig.cpp | 19 ++++++ src/backend/cpu/CpuConfig.h | 2 + src/backend/cpu/CpuLaunchData.cpp | 13 +++++ src/backend/cpu/CpuLaunchData.h | 4 ++ src/base/net/stratum/Pool.cpp | 3 +- src/core/Miner.cpp | 16 ++++++ src/core/Miner.h | 4 +- 12 files changed, 105 insertions(+), 62 deletions(-) diff --git a/src/backend/common/Workers.cpp b/src/backend/common/Workers.cpp index 629b564b..d70546d3 100644 --- a/src/backend/common/Workers.cpp +++ b/src/backend/common/Workers.cpp @@ -78,13 +78,6 @@ const xmrig::Hashrate *xmrig::Workers::hashrate() const } -template -void xmrig::Workers::add(const T &data) -{ - m_workers.push_back(new Thread(d_ptr->backend, m_workers.size(), data)); -} - - template void xmrig::Workers::setBackend(IBackend *backend) { @@ -93,8 +86,12 @@ void xmrig::Workers::setBackend(IBackend *backend) template -void xmrig::Workers::start() +void xmrig::Workers::start(const std::vector &data) { + for (const T &item : data) { + m_workers.push_back(new Thread(d_ptr->backend, m_workers.size(), item)); + } + d_ptr->hashrate = new Hashrate(m_workers.size()); for (Thread *worker : m_workers) { diff --git a/src/backend/common/Workers.h b/src/backend/common/Workers.h index c13f5e77..32d9458a 100644 --- a/src/backend/common/Workers.h +++ b/src/backend/common/Workers.h @@ -46,9 +46,8 @@ public: ~Workers(); const Hashrate *hashrate() const; - void add(const T &data); void setBackend(IBackend *backend); - void start(); + void start(const std::vector &data); void stop(); void tick(uint64_t ticks); diff --git a/src/backend/common/interfaces/IBackend.h b/src/backend/common/interfaces/IBackend.h index 8ad7bb53..6fe917cb 100644 --- a/src/backend/common/interfaces/IBackend.h +++ b/src/backend/common/interfaces/IBackend.h @@ -32,6 +32,7 @@ namespace xmrig { +class Algorithm; class Hashrate; class IWorker; class Job; @@ -43,13 +44,14 @@ class IBackend public: virtual ~IBackend() = default; - virtual const Hashrate *hashrate() const = 0; - virtual const String &profileName() const = 0; - virtual void printHashrate(bool details) = 0; - virtual void setJob(const Job &job) = 0; - virtual void start(IWorker *worker) = 0; - virtual void stop() = 0; - virtual void tick(uint64_t ticks) = 0; + virtual bool isEnabled(const Algorithm &algorithm) const = 0; + virtual const Hashrate *hashrate() const = 0; + virtual const String &profileName() const = 0; + virtual void printHashrate(bool details) = 0; + virtual void setJob(const Job &job) = 0; + virtual void start(IWorker *worker) = 0; + virtual void stop() = 0; + virtual void tick(uint64_t ticks) = 0; }; diff --git a/src/backend/cpu/CpuBackend.cpp b/src/backend/cpu/CpuBackend.cpp index f325d0ff..15a0c359 100644 --- a/src/backend/cpu/CpuBackend.cpp +++ b/src/backend/cpu/CpuBackend.cpp @@ -85,40 +85,8 @@ public: } - inline bool isReady(const Algorithm &nextAlgo) const + inline void start() { - if (!algo.isValid()) { - return false; - } - - if (nextAlgo == algo) { - return true; - } - - const CpuThreads &nextThreads = controller->config()->cpu().threads().get(nextAlgo); - - return algo.memory() == nextAlgo.memory() - && threads.size() == nextThreads.size() - && std::equal(threads.begin(), threads.end(), nextThreads.begin()); - } - - - inline void start(const Job &job) - { - const CpuConfig &cpu = controller->config()->cpu(); - - algo = job.algorithm(); - profileName = cpu.threads().profileName(job.algorithm()); - threads = cpu.threads().get(profileName); - - if (profileName.isNull() || threads.empty()) { - workers.stop(); - - LOG_WARN(YELLOW_BOLD_S "CPU disabled, no suitable configuration for algo %s", job.algorithm().shortName()); - - return; - } - LOG_INFO(GREEN_BOLD("CPU") " use profile " BLUE_BG(WHITE_BOLD_S " %s ") WHITE_BOLD_S " (" CYAN_BOLD("%zu") WHITE_BOLD(" threads)") " scratchpad " CYAN_BOLD("%zu KB"), profileName.data(), threads.size(), @@ -131,20 +99,18 @@ public: status.memory = algo.memory(); status.threads = threads.size(); - for (const CpuThread &thread : threads) { - workers.add(CpuLaunchData(controller->miner(), algo, cpu, thread)); - - status.ways += static_cast(thread.intensity()); + for (const CpuLaunchData &data : threads) { + status.ways += static_cast(data.intensity); } - workers.start(); + workers.start(threads); } Algorithm algo; Controller *controller; - CpuThreads threads; LaunchStatus status; + std::vector threads; String profileName; uv_mutex_t mutex; Workers workers; @@ -167,6 +133,12 @@ xmrig::CpuBackend::~CpuBackend() } +bool xmrig::CpuBackend::isEnabled(const Algorithm &algorithm) const +{ + return !d_ptr->controller->config()->cpu().threads().get(algorithm).empty(); +} + + const xmrig::Hashrate *xmrig::CpuBackend::hashrate() const { return d_ptr->workers.hashrate(); @@ -190,10 +162,10 @@ void xmrig::CpuBackend::printHashrate(bool details) Log::print(WHITE_BOLD_S "| CPU THREAD | AFFINITY | 10s H/s | 60s H/s | 15m H/s |"); size_t i = 0; - for (const CpuThread &thread : d_ptr->threads) { + for (const CpuLaunchData &data : d_ptr->threads) { Log::print("| %13zu | %8" PRId64 " | %7s | %7s | %7s |", i, - thread.affinity(), + data.affinity, Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval), num, sizeof num / 3), Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval), num + 8, sizeof num / 3), Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval), num + 8 * 2, sizeof num / 3) @@ -206,11 +178,26 @@ void xmrig::CpuBackend::printHashrate(bool details) void xmrig::CpuBackend::setJob(const Job &job) { - if (d_ptr->isReady(job.algorithm())) { + const CpuConfig &cpu = d_ptr->controller->config()->cpu(); + + std::vector threads = cpu.get(d_ptr->controller->miner(), job.algorithm()); + if (d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) { return; } - d_ptr->start(job); + d_ptr->algo = job.algorithm(); + d_ptr->profileName = cpu.threads().profileName(job.algorithm()); + + if (d_ptr->profileName.isNull() || threads.empty()) { + d_ptr->workers.stop(); + + LOG_WARN(YELLOW_BOLD_S "CPU disabled, no suitable configuration for algo %s", job.algorithm().shortName()); + + return; + } + + d_ptr->threads = std::move(threads); + d_ptr->start(); } diff --git a/src/backend/cpu/CpuBackend.h b/src/backend/cpu/CpuBackend.h index aabccb49..543d4459 100644 --- a/src/backend/cpu/CpuBackend.h +++ b/src/backend/cpu/CpuBackend.h @@ -44,6 +44,7 @@ public: ~CpuBackend() override; protected: + bool isEnabled(const Algorithm &algorithm) const override; const Hashrate *hashrate() const override; const String &profileName() const override; void printHashrate(bool details) override; diff --git a/src/backend/cpu/CpuConfig.cpp b/src/backend/cpu/CpuConfig.cpp index b4a9c363..457f7ef4 100644 --- a/src/backend/cpu/CpuConfig.cpp +++ b/src/backend/cpu/CpuConfig.cpp @@ -100,6 +100,25 @@ rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const } +std::vector xmrig::CpuConfig::get(const Miner *miner, const Algorithm &algorithm) const +{ + std::vector out; + const std::vector &threads = m_threads.get(algorithm); + + if (threads.empty()) { + return out; + } + + out.reserve(threads.size()); + + for (const CpuThread &thread : threads) { + out.push_back(CpuLaunchData(miner, algorithm, *this, thread)); + } + + return out; +} + + void xmrig::CpuConfig::read(const rapidjson::Value &value) { if (value.IsObject()) { diff --git a/src/backend/cpu/CpuConfig.h b/src/backend/cpu/CpuConfig.h index 88222ab1..8ff8b77c 100644 --- a/src/backend/cpu/CpuConfig.h +++ b/src/backend/cpu/CpuConfig.h @@ -27,6 +27,7 @@ #include "backend/common/Threads.h" +#include "backend/cpu/CpuLaunchData.h" #include "backend/cpu/CpuThread.h" #include "crypto/common/Assembly.h" @@ -47,6 +48,7 @@ public: bool isHwAES() const; rapidjson::Value toJSON(rapidjson::Document &doc) const; + std::vector get(const Miner *miner, const Algorithm &algorithm) const; void read(const rapidjson::Value &value); inline bool isEnabled() const { return m_enabled; } diff --git a/src/backend/cpu/CpuLaunchData.cpp b/src/backend/cpu/CpuLaunchData.cpp index 68b8e7ae..6fa458aa 100644 --- a/src/backend/cpu/CpuLaunchData.cpp +++ b/src/backend/cpu/CpuLaunchData.cpp @@ -41,6 +41,19 @@ xmrig::CpuLaunchData::CpuLaunchData(const Miner *miner, const Algorithm &algorit } +bool xmrig::CpuLaunchData::isEqual(const CpuLaunchData &other) const +{ + return (algorithm.memory() == other.algorithm.memory() + && assembly == other.assembly + && hugePages == other.hugePages + && hwAES == other.hwAES + && intensity == other.intensity + && priority == other.priority + && affinity == other.affinity + ); +} + + xmrig::CnHash::AlgoVariant xmrig::CpuLaunchData::av() const { if (intensity <= 2) { diff --git a/src/backend/cpu/CpuLaunchData.h b/src/backend/cpu/CpuLaunchData.h index 208a68b7..bb18816a 100644 --- a/src/backend/cpu/CpuLaunchData.h +++ b/src/backend/cpu/CpuLaunchData.h @@ -46,10 +46,14 @@ class CpuLaunchData public: CpuLaunchData(const Miner *miner, const Algorithm &algorithm, const CpuConfig &config, const CpuThread &thread); + bool isEqual(const CpuLaunchData &other) const; CnHash::AlgoVariant av() const; inline constexpr static Nonce::Backend backend() { return Nonce::CPU; } + inline bool operator!=(const CpuLaunchData &other) const { return !isEqual(other); } + inline bool operator==(const CpuLaunchData &other) const { return isEqual(other); } + const Algorithm algorithm; const Assembly assembly; const bool hugePages; diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index b11e1159..4d15ea47 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -192,7 +192,8 @@ bool xmrig::Pool::isEqual(const Pool &other) const && m_rigId == other.m_rigId && m_url == other.m_url && m_user == other.m_user - && m_pollInterval == other.m_pollInterval); + && m_pollInterval == other.m_pollInterval + ); } diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp index 40321662..4135e8ab 100644 --- a/src/core/Miner.cpp +++ b/src/core/Miner.cpp @@ -99,6 +99,8 @@ public: xmrig::Miner::Miner(Controller *controller) : d_ptr(new MinerPrivate(controller)) { + controller->addListener(this); + d_ptr->timer = new Timer(this); d_ptr->backends.push_back(new CpuBackend(controller)); @@ -218,6 +220,20 @@ void xmrig::Miner::stop() } +void xmrig::Miner::onConfigChanged(Config *config, Config *previousConfig) +{ + if (config->pools() != previousConfig->pools() && config->pools().active() > 0) { + return; + } + + const Job job = this->job(); + + for (IBackend *backend : d_ptr->backends) { + backend->setJob(job); + } +} + + void xmrig::Miner::onTimer(const Timer *) { double maxHashrate = 0.0; diff --git a/src/core/Miner.h b/src/core/Miner.h index f32524a7..23497eae 100644 --- a/src/core/Miner.h +++ b/src/core/Miner.h @@ -29,6 +29,7 @@ #include +#include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/interfaces/ITimerListener.h" @@ -41,7 +42,7 @@ class MinerPrivate; class IBackend; -class Miner : public ITimerListener +class Miner : public ITimerListener, public IBaseListener { public: Miner(Controller *controller); @@ -57,6 +58,7 @@ public: void stop(); protected: + void onConfigChanged(Config *config, Config *previousConfig) override; void onTimer(const Timer *timer) override; private: