-
Notifications
You must be signed in to change notification settings - Fork 8
/
stats.cpp
151 lines (134 loc) · 3.39 KB
/
stats.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/**
* Stats place holder
*
* Note: this source is C++ (requires std::map)
*
* tpruvot@github 2014
*/
#include <stdlib.h>
#include <memory.h>
#include <map>
#include "miner.h"
static std::map<uint64_t, stats_data> tlastscans;
static uint64_t uid = 0;
#define STATS_AVG_SAMPLES 30
#define STATS_PURGE_TIMEOUT 120*60 /* 120 mn */
extern uint64_t global_hashrate;
extern int opt_statsavg;
/**
* Store speed per thread
*/
void stats_remember_speed(int thr_id, uint32_t hashcount, double hashrate, uint8_t found, uint32_t height)
{
uint8_t gpu = (uint8_t) device_map[thr_id];
const uint64_t key = ((uid++ % UINT32_MAX) << 32) + gpu;
stats_data data;
// to enough hashes to give right stats
if (hashcount < 1000 || hashrate < 0.01)
return;
// first hash rates are often erroneous
if (uid < opt_n_threads * 2)
return;
memset(&data, 0, sizeof(data));
data.uid = (uint32_t) uid;
data.gpu_id = gpu;
data.thr_id = (uint8_t)thr_id;
data.tm_stat = (uint32_t) time(NULL);
data.height = height;
data.hashcount = hashcount;
data.hashfound = found;
data.hashrate = hashrate;
data.difficulty = global_diff;
if (opt_n_threads == 1 && global_hashrate && uid > 10) {
// prevent stats on too high vardiff (erroneous rates)
double ratio = (hashrate / (1.0 * global_hashrate));
if (ratio < 0.4 || ratio > 1.6)
data.ignored = 1;
}
tlastscans[key] = data;
}
/**
* Get the computed average speed
* @param thr_id int (-1 for all threads)
*/
double stats_get_speed(int thr_id, double def_speed)
{
const uint64_t keymsk = 0xffULL; // last u8 is the gpu
double speed = 0.0;
int records = 0;
std::map<uint64_t, stats_data>::reverse_iterator i = tlastscans.rbegin();
while(i != tlastscans.rend() && records < opt_statsavg)
{
if(!i->second.ignored)
if(thr_id == -1 || (keymsk & i->first) == device_map[thr_id])
{
if(i->second.hashcount > 1000)
{
speed += i->second.hashrate;
records++;
// applog(LOG_BLUE, "%d %x %.1f", thr_id, i->second.thr_id, i->second.hashrate);
}
}
++i;
}
if(records)
speed /= (double)(records);
else
speed = def_speed;
if(thr_id == -1)
speed *= (double)(opt_n_threads);
return speed;
}
/**
* Export data for api calls
*/
int stats_get_history(int thr_id, struct stats_data *data, int max_records)
{
const uint64_t keymsk = 0xffULL; // last u8 is the gpu
int records = 0;
std::map<uint64_t, stats_data>::reverse_iterator i = tlastscans.rbegin();
while (i != tlastscans.rend() && records < max_records) {
if (!i->second.ignored)
if (thr_id == -1 || (keymsk & i->first) == device_map[thr_id]) {
memcpy(&data[records], &(i->second), sizeof(struct stats_data));
records++;
}
++i;
}
return records;
}
/**
* Remove old entries to reduce memory usage
*/
void stats_purge_old(void)
{
int deleted = 0;
uint32_t now = (uint32_t) time(NULL);
uint32_t sz = tlastscans.size();
std::map<uint64_t, stats_data>::iterator i = tlastscans.begin();
while (i != tlastscans.end()) {
if (i->second.ignored || (now - i->second.tm_stat) > STATS_PURGE_TIMEOUT) {
deleted++;
tlastscans.erase(i++);
}
else ++i;
}
if (opt_debug && deleted) {
applog(LOG_DEBUG, "stats: %d/%d records purged", deleted, sz);
}
}
/**
* Reset the cache
*/
void stats_purge_all(void)
{
tlastscans.clear();
}
/**
* API meminfo
*/
void stats_getmeminfo(uint64_t *mem, uint32_t *records)
{
(*records) = tlastscans.size();
(*mem) = (*records) * sizeof(stats_data);
}