mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-11 07:17:58 +00:00
Merge pull request #198 from kanoi/stats
API add getwork stats to cgminer - accesable from API 'stats' - and devices can add stats also
This commit is contained in:
commit
85c9e0c4b6
7
README
7
README
@ -801,6 +801,13 @@ The list of requests - a (*) means it requires privileged access - and replies a
|
|||||||
restart (*) none There is no status section but just a single "RESTART"
|
restart (*) none There is no status section but just a single "RESTART"
|
||||||
reply before cgminer restarts
|
reply before cgminer restarts
|
||||||
|
|
||||||
|
stats STATS Each device or pool that has 1 or more getworks
|
||||||
|
with a list of stats regarding getwork times
|
||||||
|
The values returned by stats may change in future
|
||||||
|
versions thus would not normally be displayed
|
||||||
|
Device drivers are also able to add stats to the
|
||||||
|
end of the details returned
|
||||||
|
|
||||||
When you enable, disable or restart a GPU or PGA, you will also get Thread messages
|
When you enable, disable or restart a GPU or PGA, you will also get Thread messages
|
||||||
in the cgminer status window
|
in the cgminer status window
|
||||||
|
|
||||||
|
70
api.c
70
api.c
@ -232,6 +232,7 @@ static const char *OSINFO =
|
|||||||
#define _DEVDETAILS "DEVDETAILS"
|
#define _DEVDETAILS "DEVDETAILS"
|
||||||
#define _BYE "BYE"
|
#define _BYE "BYE"
|
||||||
#define _RESTART "RESTART"
|
#define _RESTART "RESTART"
|
||||||
|
#define _MINESTATS "STATS"
|
||||||
|
|
||||||
static const char ISJSON = '{';
|
static const char ISJSON = '{';
|
||||||
#define JSON0 "{"
|
#define JSON0 "{"
|
||||||
@ -265,6 +266,7 @@ static const char ISJSON = '{';
|
|||||||
#define JSON_BYE JSON1 _BYE JSON1
|
#define JSON_BYE JSON1 _BYE JSON1
|
||||||
#define JSON_RESTART JSON1 _RESTART JSON1
|
#define JSON_RESTART JSON1 _RESTART JSON1
|
||||||
#define JSON_CLOSE JSON3
|
#define JSON_CLOSE JSON3
|
||||||
|
#define JSON_MINESTATS JSON1 _MINESTATS JSON2
|
||||||
#define JSON_END JSON4
|
#define JSON_END JSON4
|
||||||
|
|
||||||
static const char *JSON_COMMAND = "command";
|
static const char *JSON_COMMAND = "command";
|
||||||
@ -351,6 +353,7 @@ static const char *JSON_PARAMETER = "parameter";
|
|||||||
#define MSG_ACTPOOL 67
|
#define MSG_ACTPOOL 67
|
||||||
#define MSG_REMPOOL 68
|
#define MSG_REMPOOL 68
|
||||||
#define MSG_DEVDETAILS 69
|
#define MSG_DEVDETAILS 69
|
||||||
|
#define MSG_MINESTATS 70
|
||||||
|
|
||||||
enum code_severity {
|
enum code_severity {
|
||||||
SEVERITY_ERR,
|
SEVERITY_ERR,
|
||||||
@ -476,6 +479,7 @@ struct CODES {
|
|||||||
{ SEVERITY_SUCC, MSG_REMPOOL, PARAM_BOTH, "Removed pool %d:'%s'" },
|
{ SEVERITY_SUCC, MSG_REMPOOL, PARAM_BOTH, "Removed pool %d:'%s'" },
|
||||||
{ SEVERITY_SUCC, MSG_NOTIFY, PARAM_NONE, "Notify" },
|
{ SEVERITY_SUCC, MSG_NOTIFY, PARAM_NONE, "Notify" },
|
||||||
{ SEVERITY_SUCC, MSG_DEVDETAILS,PARAM_NONE, "Device Details" },
|
{ SEVERITY_SUCC, MSG_DEVDETAILS,PARAM_NONE, "Device Details" },
|
||||||
|
{ SEVERITY_SUCC, MSG_MINESTATS,PARAM_NONE, "CGMiner stats" },
|
||||||
{ SEVERITY_FAIL, 0, 0, NULL }
|
{ SEVERITY_FAIL, 0, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2000,6 +2004,71 @@ void dosave(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
|||||||
ptr = NULL;
|
ptr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int itemstats(int i, char *id, struct cgminer_stats *stats, char *extra, bool isjson)
|
||||||
|
{
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
|
if (stats->getwork_calls || (extra != NULL && *extra))
|
||||||
|
{
|
||||||
|
if (extra == NULL)
|
||||||
|
extra = (char *)BLANK;
|
||||||
|
|
||||||
|
sprintf(buf, isjson
|
||||||
|
? "%s{\"STATS\":%d,\"ID\":\"%s\",\"Elapsed\":%.0f,\"Calls\":%d,\"Wait\":%ld.%06ld,\"Max\":%ld.%06ld,\"Min\":%ld.%06ld%s%s}"
|
||||||
|
: "%sSTATS=%d,ID=%s,Elapsed=%.0f,Calls=%d,Wait=%ld.%06ld,Max=%ld.%06ld,Min=%ld.%06ld%s%s" SEPSTR,
|
||||||
|
(isjson && (i > 0)) ? COMMA : BLANK,
|
||||||
|
i, id, total_secs, stats->getwork_calls,
|
||||||
|
stats->getwork_wait.tv_sec, stats->getwork_wait.tv_usec,
|
||||||
|
stats->getwork_wait_max.tv_sec, stats->getwork_wait_max.tv_usec,
|
||||||
|
stats->getwork_wait_min.tv_sec, stats->getwork_wait_min.tv_usec,
|
||||||
|
*extra ? COMMA : BLANK, extra);
|
||||||
|
|
||||||
|
strcat(io_buffer, buf);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
static void minerstats(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||||
|
{
|
||||||
|
char extra[BUFSIZ];
|
||||||
|
char id[20];
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
strcpy(io_buffer, message(MSG_MINESTATS, 0, NULL, isjson));
|
||||||
|
|
||||||
|
if (isjson) {
|
||||||
|
strcat(io_buffer, COMMA);
|
||||||
|
strcat(io_buffer, JSON_MINESTATS);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
for (j = 0; j < total_devices; j++) {
|
||||||
|
struct cgpu_info *cgpu = devices[j];
|
||||||
|
|
||||||
|
if (cgpu && cgpu->api) {
|
||||||
|
if (cgpu->api->get_api_stats)
|
||||||
|
cgpu->api->get_api_stats(extra, cgpu, isjson);
|
||||||
|
else
|
||||||
|
extra[0] = '\0';
|
||||||
|
|
||||||
|
sprintf(id, "%s%d", cgpu->api->name, cgpu->device_id);
|
||||||
|
i = itemstats(i, id, &(cgpu->cgminer_stats), extra, isjson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < total_pools; j++) {
|
||||||
|
struct pool *pool = pools[j];
|
||||||
|
|
||||||
|
sprintf(id, "POOL%d", j);
|
||||||
|
i = itemstats(i, id, &(pool->cgminer_stats), NULL, isjson);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isjson)
|
||||||
|
strcat(io_buffer, JSON_CLOSE);
|
||||||
|
}
|
||||||
|
|
||||||
struct CMDS {
|
struct CMDS {
|
||||||
char *name;
|
char *name;
|
||||||
void (*func)(SOCKETTYPE, char *, bool);
|
void (*func)(SOCKETTYPE, char *, bool);
|
||||||
@ -2041,6 +2110,7 @@ struct CMDS {
|
|||||||
{ "notify", notify, false },
|
{ "notify", notify, false },
|
||||||
{ "devdetails", devdetails, false },
|
{ "devdetails", devdetails, false },
|
||||||
{ "restart", dorestart, true },
|
{ "restart", dorestart, true },
|
||||||
|
{ "stats", minerstats, false },
|
||||||
{ NULL, NULL, false }
|
{ NULL, NULL, false }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
43
cgminer.c
43
cgminer.c
@ -3717,6 +3717,9 @@ void *miner_thread(void *userdata)
|
|||||||
const int thr_id = mythr->id;
|
const int thr_id = mythr->id;
|
||||||
struct cgpu_info *cgpu = mythr->cgpu;
|
struct cgpu_info *cgpu = mythr->cgpu;
|
||||||
struct device_api *api = cgpu->api;
|
struct device_api *api = cgpu->api;
|
||||||
|
struct cgminer_stats *dev_stats = &(cgpu->cgminer_stats);
|
||||||
|
struct cgminer_stats *pool_stats;
|
||||||
|
struct timeval getwork_start;
|
||||||
|
|
||||||
/* Try to cycle approximately 5 times before each log update */
|
/* Try to cycle approximately 5 times before each log update */
|
||||||
const unsigned long def_cycle = opt_log_interval / 5 ? : 1;
|
const unsigned long def_cycle = opt_log_interval / 5 ? : 1;
|
||||||
@ -3732,6 +3735,8 @@ void *miner_thread(void *userdata)
|
|||||||
bool requested = false;
|
bool requested = false;
|
||||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||||
|
|
||||||
|
gettimeofday(&getwork_start, NULL);
|
||||||
|
|
||||||
if (api->thread_init && !api->thread_init(mythr)) {
|
if (api->thread_init && !api->thread_init(mythr)) {
|
||||||
cgpu->device_last_not_well = time(NULL);
|
cgpu->device_last_not_well = time(NULL);
|
||||||
cgpu->device_not_well_reason = REASON_THREAD_FAIL_INIT;
|
cgpu->device_not_well_reason = REASON_THREAD_FAIL_INIT;
|
||||||
@ -3770,7 +3775,40 @@ void *miner_thread(void *userdata)
|
|||||||
do {
|
do {
|
||||||
gettimeofday(&tv_start, NULL);
|
gettimeofday(&tv_start, NULL);
|
||||||
|
|
||||||
|
timersub(&tv_start, &getwork_start, &getwork_start);
|
||||||
|
|
||||||
|
timeradd(&getwork_start,
|
||||||
|
&(dev_stats->getwork_wait),
|
||||||
|
&(dev_stats->getwork_wait));
|
||||||
|
if (timercmp(&getwork_start, &(dev_stats->getwork_wait_max), >)) {
|
||||||
|
dev_stats->getwork_wait_max.tv_sec = getwork_start.tv_sec;
|
||||||
|
dev_stats->getwork_wait_max.tv_usec = getwork_start.tv_usec;
|
||||||
|
}
|
||||||
|
if (timercmp(&getwork_start, &(dev_stats->getwork_wait_min), <)) {
|
||||||
|
dev_stats->getwork_wait_min.tv_sec = getwork_start.tv_sec;
|
||||||
|
dev_stats->getwork_wait_min.tv_usec = getwork_start.tv_usec;
|
||||||
|
}
|
||||||
|
dev_stats->getwork_calls++;
|
||||||
|
|
||||||
|
pool_stats = &(work->pool->cgminer_stats);
|
||||||
|
|
||||||
|
timeradd(&getwork_start,
|
||||||
|
&(pool_stats->getwork_wait),
|
||||||
|
&(pool_stats->getwork_wait));
|
||||||
|
if (timercmp(&getwork_start, &(pool_stats->getwork_wait_max), >)) {
|
||||||
|
pool_stats->getwork_wait_max.tv_sec = getwork_start.tv_sec;
|
||||||
|
pool_stats->getwork_wait_max.tv_usec = getwork_start.tv_usec;
|
||||||
|
}
|
||||||
|
if (timercmp(&getwork_start, &(pool_stats->getwork_wait_min), <)) {
|
||||||
|
pool_stats->getwork_wait_min.tv_sec = getwork_start.tv_sec;
|
||||||
|
pool_stats->getwork_wait_min.tv_usec = getwork_start.tv_usec;
|
||||||
|
}
|
||||||
|
pool_stats->getwork_calls++;
|
||||||
|
|
||||||
hashes = api->scanhash(mythr, work, work->blk.nonce + max_nonce);
|
hashes = api->scanhash(mythr, work, work->blk.nonce + max_nonce);
|
||||||
|
|
||||||
|
gettimeofday(&getwork_start, NULL);
|
||||||
|
|
||||||
if (unlikely(work_restart[thr_id].restart)) {
|
if (unlikely(work_restart[thr_id].restart)) {
|
||||||
|
|
||||||
/* Apart from device_thread 0, we stagger the
|
/* Apart from device_thread 0, we stagger the
|
||||||
@ -4899,6 +4937,9 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
load_temp_cutoffs();
|
load_temp_cutoffs();
|
||||||
|
|
||||||
|
for (i = 0; i < total_devices; ++i)
|
||||||
|
devices[i]->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET;
|
||||||
|
|
||||||
logstart += total_devices;
|
logstart += total_devices;
|
||||||
logcursor = logstart + 1;
|
logcursor = logstart + 1;
|
||||||
|
|
||||||
@ -4917,6 +4958,8 @@ int main(int argc, char *argv[])
|
|||||||
for (i = 0; i < total_pools; i++) {
|
for (i = 0; i < total_pools; i++) {
|
||||||
struct pool *pool = pools[i];
|
struct pool *pool = pools[i];
|
||||||
|
|
||||||
|
pool->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET;
|
||||||
|
|
||||||
if (!pool->rpc_userpass) {
|
if (!pool->rpc_userpass) {
|
||||||
if (!pool->rpc_user || !pool->rpc_pass)
|
if (!pool->rpc_user || !pool->rpc_pass)
|
||||||
quit(1, "No login credentials supplied for pool %u %s", i, pool->rpc_url);
|
quit(1, "No login credentials supplied for pool %u %s", i, pool->rpc_url);
|
||||||
|
14
miner.h
14
miner.h
@ -207,6 +207,7 @@ struct device_api {
|
|||||||
void (*reinit_device)(struct cgpu_info*);
|
void (*reinit_device)(struct cgpu_info*);
|
||||||
void (*get_statline_before)(char*, struct cgpu_info*);
|
void (*get_statline_before)(char*, struct cgpu_info*);
|
||||||
void (*get_statline)(char*, struct cgpu_info*);
|
void (*get_statline)(char*, struct cgpu_info*);
|
||||||
|
void (*get_api_stats)(char*, struct cgpu_info*, bool);
|
||||||
|
|
||||||
// Thread-specific functions
|
// Thread-specific functions
|
||||||
bool (*thread_prepare)(struct thr_info*);
|
bool (*thread_prepare)(struct thr_info*);
|
||||||
@ -254,6 +255,15 @@ enum dev_reason {
|
|||||||
#define REASON_DEV_THERMAL_CUTOFF_STR "Device reached thermal cutoff"
|
#define REASON_DEV_THERMAL_CUTOFF_STR "Device reached thermal cutoff"
|
||||||
#define REASON_UNKNOWN_STR "Unknown reason - code bug"
|
#define REASON_UNKNOWN_STR "Unknown reason - code bug"
|
||||||
|
|
||||||
|
#define MIN_SEC_UNSET 99999999
|
||||||
|
|
||||||
|
struct cgminer_stats {
|
||||||
|
uint32_t getwork_calls;
|
||||||
|
struct timeval getwork_wait;
|
||||||
|
struct timeval getwork_wait_max;
|
||||||
|
struct timeval getwork_wait_min;
|
||||||
|
};
|
||||||
|
|
||||||
struct cgpu_info {
|
struct cgpu_info {
|
||||||
int cgminer_id;
|
int cgminer_id;
|
||||||
struct device_api *api;
|
struct device_api *api;
|
||||||
@ -326,6 +336,8 @@ struct cgpu_info {
|
|||||||
int dev_nostart_count;
|
int dev_nostart_count;
|
||||||
int dev_over_heat_count; // It's a warning but worth knowing
|
int dev_over_heat_count; // It's a warning but worth knowing
|
||||||
int dev_thermal_cutoff_count;
|
int dev_thermal_cutoff_count;
|
||||||
|
|
||||||
|
struct cgminer_stats cgminer_stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool add_cgpu(struct cgpu_info*);
|
extern bool add_cgpu(struct cgpu_info*);
|
||||||
@ -655,6 +667,8 @@ struct pool {
|
|||||||
struct list_head curlring;
|
struct list_head curlring;
|
||||||
|
|
||||||
time_t last_share_time;
|
time_t last_share_time;
|
||||||
|
|
||||||
|
struct cgminer_stats cgminer_stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct work {
|
struct work {
|
||||||
|
Loading…
Reference in New Issue
Block a user