Skip to content

Commit 4bc727c

Browse files
committed
stats: clean up randomization code, move FastRandomContext inward
We can skip the computationally expensive dice-roll if our sample rate is zero as that means we should never send it. Also get rid of the `FastRandomContext::operator()` that isn't used anywhere else in the codebase.
1 parent 840241e commit 4bc727c

File tree

3 files changed

+33
-37
lines changed

3 files changed

+33
-37
lines changed

src/random.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,6 @@ class FastRandomContext
207207
return rand32() % nMax;
208208
}
209209

210-
uint32_t operator()(uint32_t nMax) {
211-
return rand32(nMax);
212-
}
213-
214210
/** Generate random bytes. */
215211
template <typename B = unsigned char>
216212
std::vector<B> randbytes(size_t len);

src/statsd_client.cpp

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,32 +37,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737

3838
#include <compat.h>
3939
#include <netbase.h>
40-
#include <random.h>
4140
#include <util/system.h>
4241

4342
#include <cmath>
4443
#include <cstdio>
44+
#include <random>
4545

4646
std::unique_ptr<statsd::StatsdClient> g_stats_client;
4747

4848
namespace statsd {
49-
inline bool fequal(float a, float b)
49+
bool StatsdClient::ShouldSend(float sample_rate)
5050
{
51-
const float epsilon = 0.0001;
52-
return ( fabs(a - b) < epsilon );
53-
}
54-
55-
thread_local FastRandomContext insecure_rand;
51+
sample_rate = std::clamp(sample_rate, 0.f, 1.f);
5652

57-
inline bool should_send(float sample_rate)
58-
{
59-
if ( fequal(sample_rate, 1.0) )
60-
{
61-
return true;
62-
}
53+
constexpr float EPSILON{0.0001f};
54+
/* If sample rate is 1, we should always send */
55+
if (std::fabs(sample_rate - 1.f) < EPSILON) return true;
56+
/* If sample rate is 0, we should never send */
57+
if (std::fabs(sample_rate) < EPSILON) return false;
6358

64-
float p = float(insecure_rand(std::numeric_limits<uint32_t>::max())) / float(std::numeric_limits<uint32_t>::max());
65-
return sample_rate > p;
59+
/* Sample rate is >0 and <1, roll the dice */
60+
LOCK(cs);
61+
return sample_rate > std::uniform_real_distribution<float>(0.f, 1.f)(insecure_rand);
6662
}
6763

6864
StatsdClient::StatsdClient(const std::string& host, const std::string& nodename, uint16_t port, const std::string& ns,
@@ -144,7 +140,7 @@ int StatsdClient::timing(const std::string& key, int64_t ms, float sample_rate)
144140

145141
int StatsdClient::send(std::string key, int64_t value, const std::string& type, float sample_rate)
146142
{
147-
if (!should_send(sample_rate)) {
143+
if (!ShouldSend(sample_rate)) {
148144
return 0;
149145
}
150146

@@ -154,19 +150,17 @@ int StatsdClient::send(std::string key, int64_t value, const std::string& type,
154150

155151
cleanup(key);
156152

157-
std::string buf{""};
158-
if (fequal(sample_rate, 1.0)) {
159-
buf = strprintf("%s%s:%d|%s", m_ns, key, value, type);
160-
} else {
161-
buf = strprintf("%s%s:%d|%s|@%.2f", m_ns, key, value, type, sample_rate);
153+
std::string buf{strprintf("%s%s:%d|%s", m_ns, key, value, type)};
154+
if (sample_rate < 1.f) {
155+
buf += strprintf("|@%.2f", sample_rate);
162156
}
163157

164158
return send(buf);
165159
}
166160

167161
int StatsdClient::sendDouble(std::string key, double value, const std::string& type, float sample_rate)
168162
{
169-
if (!should_send(sample_rate)) {
163+
if (!ShouldSend(sample_rate)) {
170164
return 0;
171165
}
172166

@@ -176,11 +170,9 @@ int StatsdClient::sendDouble(std::string key, double value, const std::string& t
176170

177171
cleanup(key);
178172

179-
std::string buf{""};
180-
if (fequal(sample_rate, 1.0)) {
181-
buf = strprintf("%s%s:%f|%s", m_ns, key, value, type);
182-
} else {
183-
buf = strprintf("%s%s:%f|%s|@%.2f", m_ns, key, value, type, sample_rate);
173+
std::string buf{strprintf("%s%s:%f|%s", m_ns, key, value, type)};
174+
if (sample_rate < 1.f) {
175+
buf += strprintf("|@%.2f", sample_rate);
184176
}
185177

186178
return send(buf);

src/statsd_client.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#ifndef BITCOIN_STATSD_CLIENT_H
77
#define BITCOIN_STATSD_CLIENT_H
88

9+
#include <random.h>
10+
#include <threadsafety.h>
911
#include <util/sock.h>
1012

1113
#include <string>
@@ -30,12 +32,12 @@ class StatsdClient {
3032
~StatsdClient();
3133

3234
public:
33-
int inc(const std::string& key, float sample_rate = 1.0);
34-
int dec(const std::string& key, float sample_rate = 1.0);
35-
int count(const std::string& key, int64_t value, float sample_rate = 1.0);
36-
int gauge(const std::string& key, int64_t value, float sample_rate = 1.0);
37-
int gaugeDouble(const std::string& key, double value, float sample_rate = 1.0);
38-
int timing(const std::string& key, int64_t ms, float sample_rate = 1.0);
35+
int inc(const std::string& key, float sample_rate = 1.f);
36+
int dec(const std::string& key, float sample_rate = 1.f);
37+
int count(const std::string& key, int64_t value, float sample_rate = 1.f);
38+
int gauge(const std::string& key, int64_t value, float sample_rate = 1.f);
39+
int gaugeDouble(const std::string& key, double value, float sample_rate = 1.f);
40+
int timing(const std::string& key, int64_t ms, float sample_rate = 1.f);
3941

4042
public:
4143
/**
@@ -57,6 +59,12 @@ class StatsdClient {
5759
static void cleanup(std::string& key);
5860

5961
private:
62+
bool ShouldSend(float sample_rate);
63+
64+
private:
65+
mutable Mutex cs;
66+
mutable FastRandomContext insecure_rand GUARDED_BY(cs);
67+
6068
bool m_init{false};
6169
SOCKET m_sock{INVALID_SOCKET};
6270
struct sockaddr_in m_server;

0 commit comments

Comments
 (0)