diff --git a/src/backend/common/Hashrate.cpp b/src/backend/common/Hashrate.cpp index aa4d80c7..4038e34b 100644 --- a/src/backend/common/Hashrate.cpp +++ b/src/backend/common/Hashrate.cpp @@ -1,12 +1,7 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2017-2018 XMR-Stak , + * Copyright (c) 2018-2020 SChernykh + * Copyright (c) 2016-2020 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +19,6 @@ #include -#include #include #include @@ -75,72 +69,6 @@ xmrig::Hashrate::~Hashrate() } -double xmrig::Hashrate::calc(size_t ms) const -{ - const double data = calc(0, ms); - return std::isnormal(data) ? data : 0.0; -} - - -double xmrig::Hashrate::calc(size_t threadId, size_t ms) const -{ - assert(threadId < m_threads); - if (threadId >= m_threads) { - return nan(""); - } - - uint64_t earliestHashCount = 0; - uint64_t earliestStamp = 0; - bool haveFullSet = false; - - const uint64_t timeStampLimit = xmrig::Chrono::steadyMSecs() - ms; - uint64_t* timestamps = m_timestamps[threadId]; - uint64_t* counts = m_counts[threadId]; - - const size_t idx_start = (m_top[threadId] - 1) & kBucketMask; - size_t idx = idx_start; - - uint64_t lastestStamp = timestamps[idx]; - uint64_t lastestHashCnt = counts[idx]; - - do { - if (timestamps[idx] < timeStampLimit) { - haveFullSet = (timestamps[idx] != 0); - if (idx != idx_start) { - idx = (idx + 1) & kBucketMask; - earliestStamp = timestamps[idx]; - earliestHashCount = counts[idx]; - } - break; - } - idx = (idx - 1) & kBucketMask; - } while (idx != idx_start); - - if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) { - return nan(""); - } - - if (lastestStamp - earliestStamp == 0) { - return nan(""); - } - - const auto hashes = static_cast(lastestHashCnt - earliestHashCount); - const auto time = static_cast(lastestStamp - earliestStamp) / 1000.0; - - return hashes / time; -} - - -void xmrig::Hashrate::add(size_t threadId, uint64_t count, uint64_t timestamp) -{ - const size_t top = m_top[threadId]; - m_counts[threadId][top] = count; - m_timestamps[threadId][top] = timestamp; - - m_top[threadId] = (top + 1) & kBucketMask; -} - - const char *xmrig::Hashrate::format(double h, char *buf, size_t size) { return ::format(h, buf, size); @@ -174,10 +102,69 @@ rapidjson::Value xmrig::Hashrate::toJSON(size_t threadId, rapidjson::Document &d auto &allocator = doc.GetAllocator(); Value out(kArrayType); - out.PushBack(normalize(calc(threadId + 1, ShortInterval)), allocator); - out.PushBack(normalize(calc(threadId + 1, MediumInterval)), allocator); - out.PushBack(normalize(calc(threadId + 1, LargeInterval)), allocator); + out.PushBack(normalize(calc(threadId, ShortInterval)), allocator); + out.PushBack(normalize(calc(threadId, MediumInterval)), allocator); + out.PushBack(normalize(calc(threadId, LargeInterval)), allocator); return out; } #endif + + +double xmrig::Hashrate::hashrate(size_t index, size_t ms) const +{ + assert(index < m_threads); + if (index >= m_threads) { + return nan(""); + } + + uint64_t earliestHashCount = 0; + uint64_t earliestStamp = 0; + bool haveFullSet = false; + + const uint64_t timeStampLimit = xmrig::Chrono::steadyMSecs() - ms; + uint64_t* timestamps = m_timestamps[index]; + uint64_t* counts = m_counts[index]; + + const size_t idx_start = (m_top[index] - 1) & kBucketMask; + size_t idx = idx_start; + + uint64_t lastestStamp = timestamps[idx]; + uint64_t lastestHashCnt = counts[idx]; + + do { + if (timestamps[idx] < timeStampLimit) { + haveFullSet = (timestamps[idx] != 0); + if (idx != idx_start) { + idx = (idx + 1) & kBucketMask; + earliestStamp = timestamps[idx]; + earliestHashCount = counts[idx]; + } + break; + } + idx = (idx - 1) & kBucketMask; + } while (idx != idx_start); + + if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) { + return nan(""); + } + + if (lastestStamp - earliestStamp == 0) { + return nan(""); + } + + const auto hashes = static_cast(lastestHashCnt - earliestHashCount); + const auto time = static_cast(lastestStamp - earliestStamp) / 1000.0; + + return hashes / time; +} + + +void xmrig::Hashrate::addData(size_t index, uint64_t count, uint64_t timestamp) +{ + const size_t top = m_top[index]; + m_counts[index][top] = count; + m_timestamps[index][top] = timestamp; + + m_top[index] = (top + 1) & kBucketMask; +} diff --git a/src/backend/common/Hashrate.h b/src/backend/common/Hashrate.h index 59e1afe1..ad278cfa 100644 --- a/src/backend/common/Hashrate.h +++ b/src/backend/common/Hashrate.h @@ -1,12 +1,7 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2017-2018 XMR-Stak , + * Copyright (c) 2018-2020 SChernykh + * Copyright (c) 2016-2020 XMRig , * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +21,7 @@ #define XMRIG_HASHRATE_H +#include #include #include @@ -42,7 +38,7 @@ class Hashrate public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(Hashrate) - enum Intervals { + enum Intervals : size_t { ShortInterval = 10000, MediumInterval = 60000, LargeInterval = 900000 @@ -50,11 +46,12 @@ public: Hashrate(size_t threads); ~Hashrate(); - double calc(size_t ms) const; - double calc(size_t threadId, size_t ms) const; - void add(size_t threadId, uint64_t count, uint64_t timestamp); - inline size_t threads() const { return m_threads; } + inline double calc(size_t ms) const { const double data = hashrate(0U, ms); return std::isnormal(data) ? data : 0.0; } + inline double calc(size_t threadId, size_t ms) const { return hashrate(threadId + 1, ms); } + inline size_t threads() const { return m_threads > 0U ? m_threads - 1U : 0U; } + inline void add(size_t threadId, uint64_t count, uint64_t timestamp) { addData(threadId + 1U, count, timestamp); } + inline void add(uint64_t count, uint64_t timestamp) { addData(0U, count, timestamp); } static const char *format(double h, char *buf, size_t size); static rapidjson::Value normalize(double d); @@ -65,6 +62,9 @@ public: # endif private: + double hashrate(size_t index, size_t ms) const; + void addData(size_t index, uint64_t count, uint64_t timestamp); + constexpr static size_t kBucketSize = 2 << 11; constexpr static size_t kBucketMask = kBucketSize - 1; diff --git a/src/backend/common/Workers.cpp b/src/backend/common/Workers.cpp index 8155c6fa..f015b5f7 100644 --- a/src/backend/common/Workers.cpp +++ b/src/backend/common/Workers.cpp @@ -93,7 +93,7 @@ bool xmrig::Workers::tick(uint64_t) IWorker *worker = handle->worker(); if (worker) { worker->hashrateData(hashCount, ts, rawHashes); - d_ptr->hashrate->add(handle->id() + 1, hashCount, ts); + d_ptr->hashrate->add(handle->id(), hashCount, ts); if (rawHashes == 0) { totalAvailable = false; @@ -104,7 +104,7 @@ bool xmrig::Workers::tick(uint64_t) } if (totalAvailable) { - d_ptr->hashrate->add(0, totalHashCount, Chrono::steadyMSecs()); + d_ptr->hashrate->add(totalHashCount, Chrono::steadyMSecs()); } # ifdef XMRIG_FEATURE_BENCHMARK diff --git a/src/backend/cpu/CpuBackend.cpp b/src/backend/cpu/CpuBackend.cpp index 07df8817..1e47a6c5 100644 --- a/src/backend/cpu/CpuBackend.cpp +++ b/src/backend/cpu/CpuBackend.cpp @@ -322,9 +322,9 @@ void xmrig::CpuBackend::printHashrate(bool details) Log::print("| %8zu | %8" PRId64 " | %7s | %7s | %7s |", i, data.affinity, - Hashrate::format(hashrate()->calc(i + 1, Hashrate::ShortInterval), num, sizeof num / 3), - Hashrate::format(hashrate()->calc(i + 1, Hashrate::MediumInterval), num + 8, sizeof num / 3), - Hashrate::format(hashrate()->calc(i + 1, Hashrate::LargeInterval), num + 8 * 2, sizeof num / 3) + 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) ); i++; diff --git a/src/backend/cuda/CudaBackend.cpp b/src/backend/cuda/CudaBackend.cpp index ab5b22e5..59eaab1f 100644 --- a/src/backend/cuda/CudaBackend.cpp +++ b/src/backend/cuda/CudaBackend.cpp @@ -409,9 +409,9 @@ void xmrig::CudaBackend::printHashrate(bool details) Log::print("| %8zu | %8" PRId64 " | %8s | %8s | %8s |" CYAN_BOLD(" #%u") YELLOW(" %s") GREEN(" %s"), i, data.thread.affinity(), - Hashrate::format(hashrate()->calc(i + 1, Hashrate::ShortInterval) * scale, num, sizeof num / 3), - Hashrate::format(hashrate()->calc(i + 1, Hashrate::MediumInterval) * scale, num + 16, sizeof num / 3), - Hashrate::format(hashrate()->calc(i + 1, Hashrate::LargeInterval) * scale, num + 16 * 2, sizeof num / 3), + Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval) * scale, num, sizeof num / 3), + Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval) * scale, num + 16, sizeof num / 3), + Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval) * scale, num + 16 * 2, sizeof num / 3), data.device.index(), data.device.topology().toString().data(), data.device.name().data() diff --git a/src/backend/opencl/OclBackend.cpp b/src/backend/opencl/OclBackend.cpp index 7b99700b..d0d04f37 100644 --- a/src/backend/opencl/OclBackend.cpp +++ b/src/backend/opencl/OclBackend.cpp @@ -385,9 +385,9 @@ void xmrig::OclBackend::printHashrate(bool details) Log::print("| %8zu | %8" PRId64 " | %8s | %8s | %8s |" CYAN_BOLD(" #%u") YELLOW(" %s") " %s", i, data.affinity, - Hashrate::format(hashrate()->calc(i + 1, Hashrate::ShortInterval) * scale, num, sizeof num / 3), - Hashrate::format(hashrate()->calc(i + 1, Hashrate::MediumInterval) * scale, num + 16, sizeof num / 3), - Hashrate::format(hashrate()->calc(i + 1, Hashrate::LargeInterval) * scale, num + 16 * 2, sizeof num / 3), + Hashrate::format(hashrate()->calc(i, Hashrate::ShortInterval) * scale, num, sizeof num / 3), + Hashrate::format(hashrate()->calc(i, Hashrate::MediumInterval) * scale, num + 16, sizeof num / 3), + Hashrate::format(hashrate()->calc(i, Hashrate::LargeInterval) * scale, num + 16 * 2, sizeof num / 3), data.device.index(), data.device.topology().toString().data(), data.device.printableName().data() diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp index 63bbbb54..9c96d1e3 100644 --- a/src/core/Miner.cpp +++ b/src/core/Miner.cpp @@ -203,7 +203,7 @@ public: continue; } - for (size_t i = 1; i < hr->threads(); i++) { + for (size_t i = 0; i < hr->threads(); i++) { Value thread(kArrayType); thread.PushBack(Hashrate::normalize(hr->calc(i, Hashrate::ShortInterval)), allocator); thread.PushBack(Hashrate::normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);