|
|
@@ -186,6 +186,7 @@ pthread_mutex_t control_lock;
|
|
|
|
|
|
int hw_errors;
|
|
|
int total_accepted, total_rejected;
|
|
|
+float total_accepted_weighed;
|
|
|
int total_getworks, total_stale, total_discarded;
|
|
|
static int total_queued;
|
|
|
unsigned int new_blocks;
|
|
|
@@ -1239,6 +1240,8 @@ static bool jobj_binary(const json_t *obj, const char *key,
|
|
|
|
|
|
static bool work_decode(const json_t *val, struct work *work)
|
|
|
{
|
|
|
+ unsigned char bits = 0, i;
|
|
|
+
|
|
|
if (unlikely(!jobj_binary(val, "data", work->data, sizeof(work->data), true))) {
|
|
|
applog(LOG_ERR, "JSON inval data");
|
|
|
goto err_out;
|
|
|
@@ -1274,6 +1277,22 @@ static bool work_decode(const json_t *val, struct work *work)
|
|
|
applog(LOG_ERR, "JSON inval target");
|
|
|
goto err_out;
|
|
|
}
|
|
|
+
|
|
|
+ for (i = 32; i--; )
|
|
|
+ {
|
|
|
+ if (work->target[i])
|
|
|
+ {
|
|
|
+ unsigned char j = ~work->target[i];
|
|
|
+ while (j & 0x80)
|
|
|
+ {
|
|
|
+ ++bits;
|
|
|
+ j <<= 1;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ bits += 8;
|
|
|
+ }
|
|
|
+ work->difficulty = pow(2, bits - 32);
|
|
|
|
|
|
memset(work->hash, 0, sizeof(work->hash));
|
|
|
|
|
|
@@ -1366,6 +1385,87 @@ void tailsprintf(char *f, const char *fmt, ...)
|
|
|
va_end(ap);
|
|
|
}
|
|
|
|
|
|
+static float
|
|
|
+utility_to_hashrate(double utility)
|
|
|
+{
|
|
|
+ return utility * 0x4444444;
|
|
|
+}
|
|
|
+
|
|
|
+static const char*_unitchar = "kMGTPEZY?";
|
|
|
+
|
|
|
+static void
|
|
|
+hashrate_pick_unit(float hashrate, unsigned char*unit)
|
|
|
+{
|
|
|
+ unsigned char i;
|
|
|
+ for (i = 0; i <= *unit; ++i)
|
|
|
+ hashrate /= 1e3;
|
|
|
+ while (hashrate >= 1000)
|
|
|
+ {
|
|
|
+ hashrate /= 1e3;
|
|
|
+ if (likely(_unitchar[*unit] != '?'))
|
|
|
+ ++*unit;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+enum h2bs_fmt {
|
|
|
+ H2B_NOUNIT, // "xxx.x"
|
|
|
+ H2B_SHORT, // "xxx.xMH/s"
|
|
|
+ H2B_SPACED, // "xxx.x MH/s"
|
|
|
+};
|
|
|
+static const size_t h2bs_fmt_size[] = {6, 10, 11};
|
|
|
+
|
|
|
+static char*
|
|
|
+hashrate_to_bufstr(char*buf, float hashrate, signed char unitin, enum h2bs_fmt fmt)
|
|
|
+{
|
|
|
+ unsigned char prec, i, ucp, unit;
|
|
|
+ if (unitin == -1)
|
|
|
+ {
|
|
|
+ unit = 0;
|
|
|
+ hashrate_pick_unit(hashrate, &unit);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ unit = unitin;
|
|
|
+
|
|
|
+ i = 5;
|
|
|
+ switch (fmt) {
|
|
|
+ case H2B_SPACED:
|
|
|
+ buf[i++] = ' ';
|
|
|
+ case H2B_SHORT:
|
|
|
+ buf[i++] = _unitchar[unit];
|
|
|
+ strcpy(&buf[i], "h/s");
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i <= unit; ++i)
|
|
|
+ hashrate /= 1000;
|
|
|
+ if (hashrate >= 100 || unit < 2)
|
|
|
+ prec = 1;
|
|
|
+ else
|
|
|
+ if (hashrate >= 10)
|
|
|
+ prec = 2;
|
|
|
+ else
|
|
|
+ prec = 3;
|
|
|
+ ucp = (fmt == H2B_NOUNIT ? '\0' : buf[5]);
|
|
|
+ sprintf(buf, "%5.*f", prec, hashrate);
|
|
|
+ buf[5] = ucp;
|
|
|
+ return buf;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+ti_hashrate_bufstr(char**out, float current, float average, float sharebased, enum h2bs_fmt longfmt)
|
|
|
+{
|
|
|
+ unsigned char unit = 0;
|
|
|
+
|
|
|
+ hashrate_pick_unit(current, &unit);
|
|
|
+ hashrate_pick_unit(average, &unit);
|
|
|
+ hashrate_pick_unit(sharebased, &unit);
|
|
|
+
|
|
|
+ hashrate_to_bufstr(out[0], current, unit, H2B_NOUNIT);
|
|
|
+ hashrate_to_bufstr(out[1], average, unit, H2B_NOUNIT);
|
|
|
+ hashrate_to_bufstr(out[2], sharebased, unit, longfmt);
|
|
|
+}
|
|
|
+
|
|
|
static void get_statline(char *buf, struct cgpu_info *cgpu)
|
|
|
{
|
|
|
sprintf(buf, "%s%d ", cgpu->api->name, cgpu->device_id);
|
|
|
@@ -1373,10 +1473,17 @@ static void get_statline(char *buf, struct cgpu_info *cgpu)
|
|
|
cgpu->api->get_statline_before(buf, cgpu);
|
|
|
else
|
|
|
tailsprintf(buf, " | ");
|
|
|
- tailsprintf(buf, "(%ds):%.1f (avg):%.1f Mh/s | A:%d R:%d HW:%d U:%.1f/m",
|
|
|
+ char cHr[h2bs_fmt_size[H2B_NOUNIT]], aHr[h2bs_fmt_size[H2B_NOUNIT]], uHr[h2bs_fmt_size[H2B_SPACED]];
|
|
|
+ ti_hashrate_bufstr(
|
|
|
+ (char*[]){cHr, aHr, uHr},
|
|
|
+ 1e6*cgpu->rolling,
|
|
|
+ 1e6*cgpu->total_mhashes / total_secs,
|
|
|
+ utility_to_hashrate(cgpu->utility_diff1),
|
|
|
+ H2B_SPACED);
|
|
|
+ tailsprintf(buf, "%ds:%s avg:%s u:%s | A:%d R:%d HW:%d U:%.1f/m",
|
|
|
opt_log_interval,
|
|
|
- cgpu->rolling,
|
|
|
- cgpu->total_mhashes / total_secs,
|
|
|
+ cHr, aHr,
|
|
|
+ uHr,
|
|
|
cgpu->accepted,
|
|
|
cgpu->rejected,
|
|
|
cgpu->hw_errors,
|
|
|
@@ -1445,6 +1552,7 @@ static void curses_print_devstatus(int thr_id)
|
|
|
char logline[255];
|
|
|
|
|
|
cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60;
|
|
|
+ cgpu->utility_diff1 = cgpu->accepted_weighed / ( total_secs ?: 1 ) * 60;
|
|
|
|
|
|
/* Check this isn't out of the window size */
|
|
|
if (wmove(statuswin,devcursor + cgpu->cgminer_id, 0) == ERR)
|
|
|
@@ -1458,6 +1566,13 @@ static void curses_print_devstatus(int thr_id)
|
|
|
else
|
|
|
wprintw(statuswin, " | ");
|
|
|
|
|
|
+ char cHr[h2bs_fmt_size[H2B_NOUNIT]], aHr[h2bs_fmt_size[H2B_NOUNIT]], uHr[h2bs_fmt_size[H2B_SHORT]];
|
|
|
+ ti_hashrate_bufstr(
|
|
|
+ (char*[]){cHr, aHr, uHr},
|
|
|
+ 1e6*cgpu->rolling,
|
|
|
+ 1e6*cgpu->total_mhashes / total_secs,
|
|
|
+ utility_to_hashrate(cgpu->utility_diff1),
|
|
|
+ H2B_SHORT);
|
|
|
if (cgpu->status == LIFE_DEAD)
|
|
|
wprintw(statuswin, "DEAD ");
|
|
|
else if (cgpu->status == LIFE_SICK)
|
|
|
@@ -1467,13 +1582,14 @@ static void curses_print_devstatus(int thr_id)
|
|
|
else if (cgpu->deven == DEV_RECOVER)
|
|
|
wprintw(statuswin, "REST ");
|
|
|
else
|
|
|
- wprintw(statuswin, "%5.1f", cgpu->rolling);
|
|
|
+ wprintw(statuswin, "%s", cHr);
|
|
|
adj_width(cgpu->accepted, &awidth);
|
|
|
adj_width(cgpu->rejected, &rwidth);
|
|
|
adj_width(cgpu->hw_errors, &hwwidth);
|
|
|
adj_width(cgpu->utility, &uwidth);
|
|
|
- wprintw(statuswin, "/%5.1fMh/s | A:%*d R:%*d HW:%*d U:%*.2f/m",
|
|
|
- cgpu->total_mhashes / total_secs,
|
|
|
+ wprintw(statuswin, "/%s/%s | A:%*d R:%*d HW:%*d U:%*.2f/m",
|
|
|
+ aHr,
|
|
|
+ uHr,
|
|
|
awidth, cgpu->accepted,
|
|
|
rwidth, cgpu->rejected,
|
|
|
hwwidth, cgpu->hw_errors,
|
|
|
@@ -1719,7 +1835,9 @@ static bool submit_upstream_work(const struct work *work, CURL *curl)
|
|
|
* same time is zero so there is no point adding extra locking */
|
|
|
if (json_is_true(res)) {
|
|
|
cgpu->accepted++;
|
|
|
+ cgpu->accepted_weighed += work->difficulty;
|
|
|
total_accepted++;
|
|
|
+ total_accepted_weighed += work->difficulty;
|
|
|
pool->accepted++;
|
|
|
pool->seq_rejects = 0;
|
|
|
cgpu->last_share_pool = pool->pool_no;
|
|
|
@@ -1807,6 +1925,7 @@ static bool submit_upstream_work(const struct work *work, CURL *curl)
|
|
|
}
|
|
|
|
|
|
cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60;
|
|
|
+ cgpu->utility_diff1 = cgpu->accepted_weighed / ( total_secs ?: 1 ) * 60;
|
|
|
|
|
|
if (!opt_realquiet)
|
|
|
print_status(thr_id);
|
|
|
@@ -3415,6 +3534,7 @@ static void hashmeter(int thr_id, struct timeval *diff,
|
|
|
static double rolling = 0;
|
|
|
double local_mhashes = (double)hashes_done / 1000000.0;
|
|
|
bool showlog = false;
|
|
|
+ char cHr[h2bs_fmt_size[H2B_NOUNIT]], aHr[h2bs_fmt_size[H2B_NOUNIT]], uHr[h2bs_fmt_size[H2B_SPACED]];
|
|
|
|
|
|
/* Update the last time this thread reported in */
|
|
|
if (thr_id >= 0) {
|
|
|
@@ -3491,9 +3611,17 @@ static void hashmeter(int thr_id, struct timeval *diff,
|
|
|
utility = total_accepted / ( total_secs ? total_secs : 1 ) * 60;
|
|
|
efficiency = total_getworks ? total_accepted * 100.0 / total_getworks : 0.0;
|
|
|
|
|
|
- sprintf(statusline, "%s(%ds):%.1f (avg):%.1f Mh/s | Q:%d A:%d R:%d HW:%d E:%.0f%% U:%.1f/m",
|
|
|
+ ti_hashrate_bufstr(
|
|
|
+ (char*[]){cHr, aHr, uHr},
|
|
|
+ 1e6*rolling,
|
|
|
+ 1e6*total_mhashes_done / total_secs,
|
|
|
+ utility_to_hashrate(total_accepted_weighed / (total_secs ?: 1) * 60),
|
|
|
+ H2B_SPACED);
|
|
|
+ sprintf(statusline, "%s%ds:%s avg:%s u:%s | Q:%d A:%d R:%d HW:%d E:%.0f%% U:%.1f/m",
|
|
|
want_per_device_stats ? "ALL " : "",
|
|
|
- opt_log_interval, rolling, total_mhashes_done / total_secs,
|
|
|
+ opt_log_interval,
|
|
|
+ cHr, aHr,
|
|
|
+ uHr,
|
|
|
total_getworks, total_accepted, total_rejected, hw_errors, efficiency, utility);
|
|
|
|
|
|
|