diff --git a/src/workers/Hashrate.cpp b/src/workers/Hashrate.cpp index 2a750318..0f5b97fb 100644 --- a/src/workers/Hashrate.cpp +++ b/src/workers/Hashrate.cpp @@ -34,6 +34,19 @@ #include "core/Controller.h" #include "workers/Hashrate.h" +namespace { + +uint64_t pow10(unsigned n) +{ + if (n == 0) return 1; + + uint64_t pow = 10; + for (unsigned i = 0; i < n - 1; i++) pow *= 10; + + return pow; +} + +} // namespace inline static const char *format(double h, char *buf, size_t size) { @@ -49,16 +62,19 @@ inline static const char *format(double h, char *buf, size_t size) Hashrate::Hashrate(size_t threads, xmrig::Controller *controller) : m_highest(0.0), m_threads(threads), - m_controller(controller) + m_controller(controller), + m_start_time(time(NULL)) { m_counts = new uint64_t*[threads]; m_timestamps = new uint64_t*[threads]; m_top = new uint32_t[threads]; + m_totals = new uint64_t[threads]; for (size_t i = 0; i < threads; i++) { m_counts[i] = new uint64_t[kBucketSize](); m_timestamps[i] = new uint64_t[kBucketSize](); m_top[i] = 0; + m_totals[i] = 0; } const int printTime = controller->config()->printTime(); @@ -141,9 +157,34 @@ double Hashrate::calc(size_t threadId, size_t ms) const return hashes / time; } +uint64_t Hashrate::count() const +{ + uint64_t total = 0; + for (unsigned i = 0; i < m_threads; i++) { + total += count(i); + } + + return total; +} + +uint64_t Hashrate::count(size_t threadId) const +{ + assert(threadId < m_threads); + if (threadId >= m_threads) return 0; + + return m_totals[threadId]; +} + +uint64_t Hashrate::elapsed() const +{ + return time(NULL) - m_start_time; +} + void Hashrate::add(size_t threadId, uint64_t count, uint64_t timestamp) { + m_totals[threadId] = count; + const size_t top = m_top[threadId]; m_counts[threadId][top] = count; m_timestamps[threadId][top] = timestamp; @@ -154,18 +195,29 @@ void Hashrate::add(size_t threadId, uint64_t count, uint64_t timestamp) void Hashrate::print() const { - char num1[8] = { 0 }; - char num2[8] = { 0 }; - char num3[8] = { 0 }; - char num4[8] = { 0 }; + char num1[8] = { 0 }; + char num2[8] = { 0 }; + char num3[8] = { 0 }; + char num4[8] = { 0 }; + char num5[128] = { 0 }; + char num6[128] = { 0 }; + char num7[128] = { 0 }; - LOG_INFO(m_controller->config()->isColors() ? WHITE_BOLD("speed") " 10s/60s/15m " CYAN_BOLD("%s") CYAN(" %s %s ") CYAN_BOLD("H/s") " max " CYAN_BOLD("%s H/s") - : "speed 10s/60s/15m %s %s %s H/s max %s H/s", + bool color = m_controller->config()->isColors(); + uint64_t e = elapsed(); + uint64_t c = count(); + + LOG_INFO(color ? WHITE_BOLD("speed") " 10s/60s/15m " CYAN_BOLD("%s") CYAN(" %s %s ") CYAN_BOLD("H/s") " max " CYAN_BOLD("%s H/s") : "speed 10s/60s/15m %s %s %s H/s max %s H/s", format(calc(ShortInterval), num1, sizeof(num1)), format(calc(MediumInterval), num2, sizeof(num2)), format(calc(LargeInterval), num3, sizeof(num3)), format(m_highest, num4, sizeof(num4)) - ); + ); + LOG_INFO(color ? WHITE_BOLD("totals") " time %s hashes %s rate " CYAN("%s ") CYAN_BOLD("H/s") : "totals: time %s hashes %s rate %s H/s", + timeFormat(e, num5, sizeof(num5), color), + siFormat(c, num6, sizeof(num6), color), + format(c * 1.0 / e, num7, sizeof(num7)) + ); } @@ -189,6 +241,65 @@ const char *Hashrate::format(double h, char *buf, size_t size) return ::format(h, buf, size); } +const char *Hashrate::siFormat(uint64_t h, char *buf, size_t size, bool color) +{ + + char c[2]; + c[1] = '\0'; + uint64_t d = 0; + + if (h > pow10(9)) { + c[0] = 'G'; + d = (h % pow10(9)) / pow10(6); + h /= pow10(9); + } + else if (h > pow10(6)) { + c[0] = 'M'; + d = (h % pow10(6)) / pow10(3); + h /= pow10(6); + } + else if (h > pow10(3)) { + c[0] = 'k'; + d = h % pow10(3); + h /= pow10(3); + } + else { + snprintf(buf, size, (color) ? CYAN("%lu") : "%lu", h); + return buf; + } + + snprintf(buf, size, (color) ? CYAN("%lu.%03lu") CYAN_BOLD("%s") : "%lu.%03lu%s", h, d, c); + return buf; +} + +const char *Hashrate::timeFormat(uint64_t s, char *buf, size_t size, bool color) +{ + uint64_t d = 0; + uint64_t h = 0; + uint64_t m = 0; + + if (s > 3600 * 24) { + d = s / (3600*24); + s = s % (3600*24); + } + if (s > 3600) { + h = s / (3600); + s = s % (3600); + } + if (s > 60) { + m = s / (60); + s = s % (60); + } + + if (!color) { + snprintf(buf, size, "%02lud::%02luh::%02lum::%02lus", d, h, m, s); + } + else { + snprintf(buf, size, CYAN("%02lu") CYAN_BOLD("d") CYAN("%02lu") CYAN_BOLD("h") CYAN("%02lu") CYAN_BOLD("m") CYAN("%02lu") CYAN_BOLD("s"), d, h, m, s); + } + return buf; +} + void Hashrate::onReport(uv_timer_t *handle) { diff --git a/src/workers/Hashrate.h b/src/workers/Hashrate.h index e766f117..02726ba5 100644 --- a/src/workers/Hashrate.h +++ b/src/workers/Hashrate.h @@ -46,6 +46,9 @@ public: Hashrate(size_t threads, xmrig::Controller *controller); double calc(size_t ms) const; double calc(size_t threadId, size_t ms) const; + uint64_t count() const; + uint64_t count(size_t threadId) const; + uint64_t elapsed() const; void add(size_t threadId, uint64_t count, uint64_t timestamp); void print() const; void stop(); @@ -55,6 +58,8 @@ public: inline size_t threads() const { return m_threads; } static const char *format(double h, char *buf, size_t size); + static const char *siFormat(uint64_t h, char *buf, size_t size, bool color=false); + static const char *timeFormat(uint64_t t, char *buf, size_t size, bool color=false); private: static void onReport(uv_timer_t *handle); @@ -65,10 +70,12 @@ private: double m_highest; size_t m_threads; uint32_t* m_top; + uint64_t* m_totals; uint64_t** m_counts; uint64_t** m_timestamps; uv_timer_t m_timer; xmrig::Controller *m_controller; + time_t m_start_time; };