From 36c1cb23e0021ee78abfeb3dcfd2f3e09c89c620 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 24 Oct 2020 13:53:49 +0700 Subject: [PATCH] Implemented static benchmark verification (--bench --seed --hash) --- src/backend/common/Benchmark.cpp | 38 +++++++-- src/backend/common/Benchmark.h | 18 +++-- src/backend/common/Workers.cpp | 81 +++++++++---------- src/backend/common/Workers.h | 10 ++- src/backend/cpu/CpuBackend.cpp | 29 ++++--- src/base/net/stratum/DaemonClient.cpp | 1 + src/base/net/stratum/DaemonClient.h | 2 +- src/base/net/stratum/Job.cpp | 12 +++ src/base/net/stratum/Job.h | 33 +++++--- .../net/stratum/benchmark/BenchClient.cpp | 52 +++++++++--- src/base/net/stratum/benchmark/BenchClient.h | 15 +++- .../net/stratum/benchmark/BenchConfig.cpp | 5 ++ src/core/Miner.cpp | 2 +- src/net/Network.cpp | 29 +++---- 14 files changed, 220 insertions(+), 107 deletions(-) diff --git a/src/backend/common/Benchmark.cpp b/src/backend/common/Benchmark.cpp index f87eeba2c..979c82b37 100644 --- a/src/backend/common/Benchmark.cpp +++ b/src/backend/common/Benchmark.cpp @@ -21,6 +21,7 @@ #include "backend/common/interfaces/IWorker.h" #include "base/io/log/Log.h" #include "base/io/log/Tags.h" +#include "base/net/stratum/Job.h" #include "base/tools/Chrono.h" @@ -39,6 +40,17 @@ static uint64_t hashCheck[2][10] = { } // namespace xmrig +xmrig::Benchmark::Benchmark(const Job &job, size_t workers, const IBackend *backend) : + m_algo(job.algorithm()), + m_backend(backend), + m_workers(workers), + m_token(job.benchToken()), + m_end(job.benchSize()), + m_hash(job.benchHash()) +{ +} + + bool xmrig::Benchmark::finish(uint64_t totalHashCount) { m_reset = true; @@ -48,13 +60,8 @@ bool xmrig::Benchmark::finish(uint64_t totalHashCount) return false; } - const double dt = (m_doneTime - m_startTime) / 1000.0; - uint64_t checkData = 0; - const uint32_t N = (m_end / 1000000) - 1; - - if (((m_algo == Algorithm::RX_0) || (m_algo == Algorithm::RX_WOW)) && ((m_end % 1000000) == 0) && (N < 10)) { - checkData = hashCheck[(m_algo == Algorithm::RX_0) ? 0 : 1][N]; - } + const double dt = static_cast(m_doneTime - m_startTime) / 1000.0; + uint64_t checkData = referenceHash(); const char *color = checkData ? ((m_data == checkData) ? GREEN_BOLD_S : RED_BOLD_S) : BLACK_BOLD_S; @@ -77,7 +84,7 @@ void xmrig::Benchmark::printProgress() const return; } - const double dt = (Chrono::steadyMSecs() - m_startTime) / 1000.0; + const double dt = static_cast(Chrono::steadyMSecs() - m_startTime) / 1000.0; const double percent = static_cast(m_current) / m_end * 100.0; LOG_NOTICE("%s " MAGENTA_BOLD("%5.2f%% ") CYAN_BOLD("%" PRIu64) CYAN("/%" PRIu64) BLACK_BOLD(" (%.3fs)"), Tags::bench(), percent, m_current, m_end, dt); @@ -101,3 +108,18 @@ void xmrig::Benchmark::tick(IWorker *worker) m_data ^= worker->benchData(); m_doneTime = std::max(doneTime, m_doneTime); } + + +uint64_t xmrig::Benchmark::referenceHash() const +{ + if (m_hash) { + return m_hash; + } + + const uint32_t N = (m_end / 1000000) - 1; + if (((m_algo == Algorithm::RX_0) || (m_algo == Algorithm::RX_WOW)) && ((m_end % 1000000) == 0) && (N < 10)) { + return hashCheck[(m_algo == Algorithm::RX_0) ? 0 : 1][N]; + } + + return 0; +} diff --git a/src/backend/common/Benchmark.h b/src/backend/common/Benchmark.h index 833d5fe32..2029f8ea0 100644 --- a/src/backend/common/Benchmark.h +++ b/src/backend/common/Benchmark.h @@ -20,14 +20,17 @@ #define XMRIG_BENCHMARK_H -#include "base/tools/Object.h" #include "base/crypto/Algorithm.h" +#include "base/tools/Object.h" +#include "base/tools/String.h" namespace xmrig { +class IBackend; class IWorker; +class Job; class Benchmark @@ -35,7 +38,7 @@ class Benchmark public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(Benchmark) - Benchmark(uint32_t end, const Algorithm &algo, size_t workers) : m_algo(algo), m_workers(workers), m_end(end) {} + Benchmark(const Job &job, size_t workers, const IBackend *backend); ~Benchmark() = default; bool finish(uint64_t totalHashCount); @@ -44,10 +47,15 @@ public: void tick(IWorker *worker); private: + uint64_t referenceHash() const; + bool m_reset = false; - const Algorithm m_algo = Algorithm::RX_0; - const size_t m_workers = 0; - const uint64_t m_end = 0; + const Algorithm m_algo; + const IBackend *m_backend; + const size_t m_workers; + const String m_token; + const uint64_t m_end; + const uint64_t m_hash; uint32_t m_done = 0; uint64_t m_current = 0; uint64_t m_data = 0; diff --git a/src/backend/common/Workers.cpp b/src/backend/common/Workers.cpp index 272cfb59e..4413ece6b 100644 --- a/src/backend/common/Workers.cpp +++ b/src/backend/common/Workers.cpp @@ -87,13 +87,6 @@ xmrig::Workers::~Workers() } -template -xmrig::Benchmark *xmrig::Workers::benchmark() const -{ - return d_ptr->benchmark.get(); -} - - template static void getHashrateData(xmrig::IWorker* worker, uint64_t& hashCount, uint64_t& timeStamp) { @@ -168,41 +161,6 @@ void xmrig::Workers::setBackend(IBackend *backend) } -template -void xmrig::Workers::start(const std::vector &data) -{ -# ifdef XMRIG_FEATURE_BENCHMARK - if (!data.empty() && data.front().benchSize) { - d_ptr->benchmark = std::make_shared(data.front().benchSize, data.front().algorithm, data.size()); - } -# endif - - for (const T &item : data) { - m_workers.push_back(new Thread(d_ptr->backend, m_workers.size(), item)); - } - - d_ptr->hashrate = std::make_shared(m_workers.size()); - Nonce::touch(T::backend()); - - for (Thread *worker : m_workers) { - worker->start(Workers::onReady); - -# ifdef XMRIG_FEATURE_BENCHMARK - if (!d_ptr->benchmark) -# endif - { - std::this_thread::sleep_for(std::chrono::milliseconds(20)); - } - } - -# ifdef XMRIG_FEATURE_BENCHMARK - if (d_ptr->benchmark) { - d_ptr->benchmark->start(); - } -# endif -} - - template void xmrig::Workers::stop() { @@ -219,6 +177,22 @@ void xmrig::Workers::stop() } +#ifdef XMRIG_FEATURE_BENCHMARK +template +void xmrig::Workers::start(const std::vector &data, const std::shared_ptr &benchmark) +{ + if (!benchmark) { + return start(data, true); + } + + start(data, false); + + d_ptr->benchmark = benchmark; + d_ptr->benchmark->start(); +} +#endif + + template xmrig::IWorker *xmrig::Workers::create(Thread *) { @@ -250,6 +224,29 @@ void xmrig::Workers::onReady(void *arg) } +template +void xmrig::Workers::start(const std::vector &data, bool sleep) +{ + for (const auto &item : data) { + m_workers.push_back(new Thread(d_ptr->backend, m_workers.size(), item)); + } + + d_ptr->hashrate = std::make_shared(m_workers.size()); + Nonce::touch(T::backend()); + + for (auto worker : m_workers) { + worker->start(Workers::onReady); + + // This sleep is important for optimal caching! + // Threads must allocate scratchpads in order so that adjacent cores will use adjacent scratchpads + // Sub-optimal caching can result in up to 0.5% hashrate penalty + if (sleep) { + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } + } +} + + namespace xmrig { diff --git a/src/backend/common/Workers.h b/src/backend/common/Workers.h index 3b7fa0191..5cdc78a2e 100644 --- a/src/backend/common/Workers.h +++ b/src/backend/common/Workers.h @@ -59,18 +59,24 @@ public: Workers(); ~Workers(); - Benchmark *benchmark() const; + inline void start(const std::vector &data) { start(data, true); } + bool tick(uint64_t ticks); const Hashrate *hashrate() const; void jobEarlyNotification(const Job&); void setBackend(IBackend *backend); - void start(const std::vector &data); void stop(); +# ifdef XMRIG_FEATURE_BENCHMARK + void start(const std::vector &data, const std::shared_ptr &benchmark); +# endif + private: static IWorker *create(Thread *handle); static void onReady(void *arg); + void start(const std::vector &data, bool sleep); + std::vector *> m_workers; WorkersPrivate *d_ptr; }; diff --git a/src/backend/cpu/CpuBackend.cpp b/src/backend/cpu/CpuBackend.cpp index a5c9c406f..82201a352 100644 --- a/src/backend/cpu/CpuBackend.cpp +++ b/src/backend/cpu/CpuBackend.cpp @@ -138,10 +138,7 @@ private: class CpuBackendPrivate { public: - inline CpuBackendPrivate(Controller *controller) : - controller(controller) - { - } + inline CpuBackendPrivate(Controller *controller) : controller(controller) {} inline void start() @@ -155,7 +152,12 @@ public: ); status.start(threads, algo.l3()); + +# ifdef XMRIG_FEATURE_BENCHMARK + workers.start(threads, benchmark); +# else workers.start(threads); +# endif } @@ -204,6 +206,10 @@ public: std::vector threads; String profileName; Workers workers; + +# ifdef XMRIG_FEATURE_BENCHMARK + std::shared_ptr benchmark; +# endif }; @@ -338,7 +344,7 @@ void xmrig::CpuBackend::setJob(const Job &job) return stop(); } - const CpuConfig &cpu = d_ptr->controller->config()->cpu(); + const auto &cpu = d_ptr->controller->config()->cpu(); std::vector threads = cpu.get(d_ptr->controller->miner(), job.algorithm(), d_ptr->controller->config()->pools().benchSize()); if (!d_ptr->threads.empty() && d_ptr->threads.size() == threads.size() && std::equal(d_ptr->threads.begin(), d_ptr->threads.end(), threads.begin())) { @@ -356,6 +362,12 @@ void xmrig::CpuBackend::setJob(const Job &job) stop(); +# ifdef XMRIG_FEATURE_BENCHMARK + if (job.benchSize()) { + d_ptr->benchmark = std::make_shared(job, threads.size(), this); + } +# endif + d_ptr->threads = std::move(threads); d_ptr->start(); } @@ -469,15 +481,14 @@ void xmrig::CpuBackend::handleRequest(IApiRequest &request) #ifdef XMRIG_FEATURE_BENCHMARK xmrig::Benchmark *xmrig::CpuBackend::benchmark() const { - return d_ptr->workers.benchmark(); + return d_ptr->benchmark.get(); } void xmrig::CpuBackend::printBenchProgress() const { - auto benchmark = d_ptr->workers.benchmark(); - if (benchmark) { - benchmark->printProgress(); + if (d_ptr->benchmark) { + d_ptr->benchmark->printProgress(); } } #endif diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 59e2a6ff8..a8986747d 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -34,6 +34,7 @@ #include "base/kernel/interfaces/IClientListener.h" #include "base/net/http/Fetch.h" #include "base/net/http/HttpData.h" +#include "base/net/http/HttpListener.h" #include "base/net/stratum/SubmitResult.h" #include "base/tools/Buffer.h" #include "base/tools/Timer.h" diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index 0c3df6a1b..94858b50b 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -27,8 +27,8 @@ #define XMRIG_DAEMONCLIENT_H +#include "base/kernel/interfaces/IHttpListener.h" #include "base/kernel/interfaces/ITimerListener.h" -#include "base/net/http/HttpListener.h" #include "base/net/stratum/BaseClient.h" #include "base/tools/Object.h" diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index fc17b5102..f791a9568 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -174,6 +174,12 @@ void xmrig::Job::copy(const Job &other) memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob)); memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget)); # endif + +# ifdef XMRIG_FEATURE_BENCHMARK + m_benchSize = other.m_benchSize; + m_benchHash = other.m_benchHash; + m_benchToken = other.m_benchToken; +# endif } @@ -205,4 +211,10 @@ void xmrig::Job::move(Job &&other) memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob)); memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget)); # endif + +# ifdef XMRIG_FEATURE_BENCHMARK + m_benchSize = other.m_benchSize; + m_benchHash = other.m_benchHash; + m_benchToken = std::move(other.m_benchToken); +# endif } diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 33a521d3e..ac564d37b 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -98,18 +98,27 @@ public: inline void setPoolWallet(const String &poolWallet) { m_poolWallet = poolWallet; } # ifdef XMRIG_PROXY_PROJECT - inline char *rawBlob() { return m_rawBlob; } - inline const char *rawBlob() const { return m_rawBlob; } - inline const char *rawTarget() const { return m_rawTarget; } - inline const String &rawSeedHash() const { return m_rawSeedHash; } + inline char *rawBlob() { return m_rawBlob; } + inline const char *rawBlob() const { return m_rawBlob; } + inline const char *rawTarget() const { return m_rawTarget; } + inline const String &rawSeedHash() const { return m_rawSeedHash; } # endif - static inline uint64_t toDiff(uint64_t target) { return target ? (0xFFFFFFFFFFFFFFFFULL / target) : 0; } + static inline uint64_t toDiff(uint64_t target) { return target ? (0xFFFFFFFFFFFFFFFFULL / target) : 0; } - inline bool operator!=(const Job &other) const { return !isEqual(other); } - inline bool operator==(const Job &other) const { return isEqual(other); } - inline Job &operator=(const Job &other) { copy(other); return *this; } - inline Job &operator=(Job &&other) noexcept { move(std::move(other)); return *this; } + inline bool operator!=(const Job &other) const { return !isEqual(other); } + inline bool operator==(const Job &other) const { return isEqual(other); } + inline Job &operator=(const Job &other) { copy(other); return *this; } + inline Job &operator=(Job &&other) noexcept { move(std::move(other)); return *this; } + +# ifdef XMRIG_FEATURE_BENCHMARK + inline const String &benchToken() const { return m_benchToken; } + inline uint32_t benchSize() const { return m_benchSize; } + inline uint64_t benchHash() const { return m_benchHash; } + inline void setBenchHash(uint64_t benchHash) { m_benchHash = benchHash; } + inline void setBenchSize(uint32_t size) { m_benchSize = size; } + inline void setBenchToken(const String &token) { m_benchToken = token; } +# endif private: void copy(const Job &other); @@ -135,6 +144,12 @@ private: char m_rawTarget[24]{}; String m_rawSeedHash; # endif + +# ifdef XMRIG_FEATURE_BENCHMARK + String m_benchToken; + uint32_t m_benchSize = 0; + uint64_t m_benchHash = 0; +# endif }; diff --git a/src/base/net/stratum/benchmark/BenchClient.cpp b/src/base/net/stratum/benchmark/BenchClient.cpp index 710351542..96c5982fe 100644 --- a/src/base/net/stratum/benchmark/BenchClient.cpp +++ b/src/base/net/stratum/benchmark/BenchClient.cpp @@ -19,35 +19,58 @@ #include "base/net/stratum/benchmark/BenchClient.h" #include "3rdparty/rapidjson/document.h" #include "base/kernel/interfaces/IClientListener.h" +#include "base/net/http/HttpListener.h" #include "base/net/stratum/benchmark/BenchConfig.h" xmrig::BenchClient::BenchClient(const std::shared_ptr &benchmark, IClientListener* listener) : - m_listener(listener) + m_listener(listener), + m_benchmark(benchmark) { - m_job.setAlgorithm(benchmark->algorithm()); + m_httpListener = std::make_shared(this); std::vector blob(112 * 2 + 1, '0'); - blob.back() = '\0'; + m_job.setBlob(blob.data()); + m_job.setAlgorithm(m_benchmark->algorithm()); + m_job.setDiff(std::numeric_limits::max()); + m_job.setHeight(1); + m_job.setBenchSize(m_benchmark->size()); + m_job.setBenchHash(m_benchmark->hash()); + + if (m_benchmark->isSubmit()) { + m_mode = ONLINE_BENCH; + + return; + } + + if (!m_benchmark->id().isEmpty()) { + m_job.setId(m_benchmark->id()); + m_mode = ONLINE_VERIFY; + + return; + } + + m_job.setId("00000000"); + + if (m_job.benchHash() && m_job.setSeedHash(m_benchmark->seed())) { + m_mode = STATIC_VERIFY; + + return; + } blob[Job::kMaxSeedSize * 2] = '\0'; m_job.setSeedHash(blob.data()); - - m_job.setDiff(uint64_t(-1)); - m_job.setHeight(1); - - m_job.setId("00000000"); } void xmrig::BenchClient::connect() { - m_listener->onLoginSuccess(this); - - rapidjson::Value params; - m_listener->onJobReceived(this, m_job, params); + if (m_mode == STATIC_BENCH || m_mode == STATIC_VERIFY) { + m_listener->onLoginSuccess(this); + m_listener->onJobReceived(this, m_job, rapidjson::Value()); + } } @@ -55,3 +78,8 @@ void xmrig::BenchClient::setPool(const Pool &pool) { m_pool = pool; } + + +void xmrig::BenchClient::onHttpData(const HttpData &data) +{ +} diff --git a/src/base/net/stratum/benchmark/BenchClient.h b/src/base/net/stratum/benchmark/BenchClient.h index eb27c0012..3013a1e93 100644 --- a/src/base/net/stratum/benchmark/BenchClient.h +++ b/src/base/net/stratum/benchmark/BenchClient.h @@ -21,12 +21,13 @@ #include "base/net/stratum/Client.h" +#include "base/kernel/interfaces/IHttpListener.h" namespace xmrig { -class BenchClient : public IClient +class BenchClient : public IClient, public IHttpListener { public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(BenchClient) @@ -63,12 +64,24 @@ public: void connect() override; void setPool(const Pool &pool) override; +protected: + void onHttpData(const HttpData &data) override; + private: + enum Mode : uint32_t { + STATIC_BENCH, + ONLINE_BENCH, + STATIC_VERIFY, + ONLINE_VERIFY + }; + IClientListener* m_listener; Job m_job; Pool m_pool; std::shared_ptr m_benchmark; + std::shared_ptr m_httpListener; String m_ip; + Mode m_mode = STATIC_BENCH; }; diff --git a/src/base/net/stratum/benchmark/BenchConfig.cpp b/src/base/net/stratum/benchmark/BenchConfig.cpp index 022ec488c..5be4cdddd 100644 --- a/src/base/net/stratum/benchmark/BenchConfig.cpp +++ b/src/base/net/stratum/benchmark/BenchConfig.cpp @@ -50,6 +50,11 @@ xmrig::BenchConfig::BenchConfig(uint32_t size, const String &id, const rapidjson if (!m_algorithm.isValid() || m_algorithm.family() != Algorithm::RANDOM_X) { m_algorithm = Algorithm::RX_0; } + + const char *hash = Json::getString(object, kHash); + if (hash) { + m_hash = strtoull(hash, nullptr, 16); + } } diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp index b4e1ec7f6..8f38d59fb 100644 --- a/src/core/Miner.cpp +++ b/src/core/Miner.cpp @@ -341,9 +341,9 @@ public: Algorithm algorithm; Algorithms algorithms; bool active = false; + bool battery_power = false; bool enabled = true; bool reset = true; - bool battery_power = false; Controller *controller; Job job; mutable std::map maxHashrate; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 6432db6e9..1c1aa8e20 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -128,14 +128,6 @@ void xmrig::Network::onActive(IStrategy *strategy, IClient *client) # ifdef XMRIG_FEATURE_BENCHMARK if (pool.mode() == Pool::MODE_BENCHMARK) { - m_benchSize = pool.benchSize(); - - LOG_NOTICE("%s " MAGENTA_BOLD("start benchmark ") "hashes " CYAN_BOLD("%" PRIu64 "M") " algo " WHITE_BOLD("%s") " print_time " CYAN_BOLD("%us"), - Tags::bench(), - pool.benchSize() / 1000000, - client->job().algorithm().shortName(), - m_controller->config()->printTime()); - return; } # endif @@ -272,17 +264,20 @@ void xmrig::Network::setJob(IClient *client, const Job &job, bool donate) const char *scale = NetworkState::scaleDiff(diff); # ifdef XMRIG_FEATURE_BENCHMARK - if (!m_benchSize) + if (job.benchSize()) { + LOG_NOTICE("%s " MAGENTA_BOLD("start benchmark ") "hashes " CYAN_BOLD("%" PRIu64 "M") " algo " WHITE_BOLD("%s") " print_time " CYAN_BOLD("%us"), + Tags::bench(), + job.benchSize() / 1000000, + job.algorithm().shortName(), + m_controller->config()->printTime()); + + LOG_NOTICE("%s " WHITE_BOLD("seed ") BLACK_BOLD("%s"), Tags::bench(), job.seed().toHex().data()); + } + else # endif { - if (job.height()) { - LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), - Tags::network(), client->pool().host().data(), client->pool().port(), diff, scale, job.algorithm().shortName(), job.height()); - } - else { - LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s"), - Tags::network(), client->pool().host().data(), client->pool().port(), diff, scale, job.algorithm().shortName()); - } + LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), + Tags::network(), client->pool().host().data(), client->pool().port(), diff, scale, job.algorithm().shortName(), job.height()); } if (!donate && m_donate) {