Skip to content

Commit bf6ed1d

Browse files
committed
Fix issues with 64 bit keyspace
main issues were: * --requests was only 32bit * --key-pattern=P:P was incompatible with large keyspace * random number generator was unfair (some of the upper bits were constant)
1 parent fdd22d8 commit bf6ed1d

File tree

6 files changed

+42
-37
lines changed

6 files changed

+42
-37
lines changed

client.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ bool client::setup_client(benchmark_config *config, abstract_protocol *protocol,
108108
m_obj_gen->set_random_seed(config->next_client_idx);
109109

110110
if (config->key_pattern[0]=='P') {
111-
int range = (config->key_maximum - config->key_minimum)/(config->clients*config->threads) + 1;
112-
int min = config->key_minimum + range*config->next_client_idx;
113-
int max = min+range;
111+
unsigned long long range = (config->key_maximum - config->key_minimum)/(config->clients*config->threads) + 1;
112+
unsigned long long min = config->key_minimum + range*config->next_client_idx;
113+
unsigned long long max = min+range;
114114
if(config->next_client_idx==(int)(config->clients*config->threads)-1)
115115
max = config->key_maximum; //the last clients takes the leftover
116116
m_obj_gen->set_key_range(min, max);

client.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,13 @@ class client : public connections_manager {
152152
object_generator* m_obj_gen;
153153
run_stats m_stats;
154154

155-
unsigned int m_reqs_processed; // requests processed (responses received)
156-
unsigned int m_reqs_generated; // requests generated (wait for responses)
155+
unsigned long long m_reqs_processed; // requests processed (responses received)
156+
unsigned long long m_reqs_generated; // requests generated (wait for responses)
157157
unsigned int m_set_ratio_count; // number of sets counter (overlaps on ratio)
158158
unsigned int m_get_ratio_count; // number of gets counter (overlaps on ratio)
159159

160-
unsigned long m_tot_set_ops; // Total number of SET ops
161-
unsigned long m_tot_wait_ops; // Total number of WAIT ops
160+
unsigned long long m_tot_set_ops; // Total number of SET ops
161+
unsigned long long m_tot_wait_ops; // Total number of WAIT ops
162162

163163
keylist *m_keylist; // used to construct multi commands
164164

@@ -174,15 +174,15 @@ class client : public connections_manager {
174174
run_stats* get_stats(void) { return &m_stats; }
175175

176176
// client manager api's
177-
unsigned int get_reqs_processed() {
177+
unsigned long long get_reqs_processed() {
178178
return m_reqs_processed;
179179
}
180180

181181
void inc_reqs_processed() {
182182
m_reqs_processed++;
183183
}
184184

185-
unsigned int get_reqs_generated() {
185+
unsigned long long get_reqs_generated() {
186186
return m_reqs_generated;
187187
}
188188

connections_manager.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121

2222
class connections_manager {
2323
public:
24-
virtual unsigned int get_reqs_processed(void) = 0;
24+
virtual unsigned long long get_reqs_processed(void) = 0;
2525
virtual void inc_reqs_processed(void) = 0;
26-
virtual unsigned int get_reqs_generated(void) = 0;
26+
virtual unsigned long long get_reqs_generated(void) = 0;
2727
virtual void inc_reqs_generated(void) = 0;
2828
virtual bool finished(void) = 0;
2929

memtier_benchmark.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static void config_print(FILE *file, struct benchmark_config *cfg)
8484
"client_stats = %s\n"
8585
"run_count = %u\n"
8686
"debug = %u\n"
87-
"requests = %u\n"
87+
"requests = %llu\n"
8888
"clients = %u\n"
8989
"threads = %u\n"
9090
"test_time = %u\n"
@@ -172,7 +172,7 @@ static void config_print_to_json(json_handler * jsonhandler, struct benchmark_co
172172
jsonhandler->write_obj("client_stats" ,"\"%s\"", cfg->client_stats);
173173
jsonhandler->write_obj("run_count" ,"%u", cfg->run_count);
174174
jsonhandler->write_obj("debug" ,"%u", cfg->debug);
175-
jsonhandler->write_obj("requests" ,"%u", cfg->requests);
175+
jsonhandler->write_obj("requests" ,"%llu", cfg->requests);
176176
jsonhandler->write_obj("clients" ,"%u", cfg->clients);
177177
jsonhandler->write_obj("threads" ,"%u", cfg->threads);
178178
jsonhandler->write_obj("test_time" ,"%u", cfg->test_time);
@@ -237,11 +237,11 @@ static void config_init_defaults(struct benchmark_config *cfg)
237237
cfg->key_pattern = "R:R";
238238
if (!cfg->data_size_pattern)
239239
cfg->data_size_pattern = "R";
240-
if (cfg->requests == (unsigned int)-1) {
240+
if (cfg->requests == (unsigned long long)-1) {
241241
cfg->requests = cfg->key_maximum - cfg->key_minimum;
242242
if (strcmp(cfg->key_pattern, "P:P")==0)
243243
cfg->requests = cfg->requests / (cfg->clients * cfg->threads) + 1;
244-
printf("setting requests to %d\n", cfg->requests);
244+
printf("setting requests to %llu\n", cfg->requests);
245245
}
246246
if (!cfg->requests && !cfg->test_time)
247247
cfg->requests = 10000;
@@ -443,7 +443,7 @@ static int config_parse_args(int argc, char *argv[], struct benchmark_config *cf
443443
if (strcmp(optarg, "allkeys")==0)
444444
cfg->requests = -1;
445445
else {
446-
cfg->requests = (unsigned int) strtoul(optarg, &endptr, 10);
446+
cfg->requests = (unsigned long long) strtoull(optarg, &endptr, 10);
447447
if (!cfg->requests || !endptr || *endptr != '\0') {
448448
fprintf(stderr, "error: requests must be greater than zero.\n");
449449
return -1;
@@ -1165,16 +1165,16 @@ int main(int argc, char *argv[])
11651165
fprintf(outfile,
11661166
"%-9u Threads\n"
11671167
"%-9u Connections per thread\n"
1168-
"%-9u %s\n",
1168+
"%-9llu %s\n",
11691169
cfg.threads, cfg.clients,
1170-
cfg.requests > 0 ? cfg.requests : cfg.test_time,
1170+
(unsigned long long)(cfg.requests > 0 ? cfg.requests : cfg.test_time),
11711171
cfg.requests > 0 ? "Requests per thread" : "Seconds");
11721172
if (jsonhandler != NULL){
11731173
jsonhandler->open_nesting("run information");
11741174
jsonhandler->write_obj("Threads","%u",cfg.threads);
11751175
jsonhandler->write_obj("Connections per thread","%u",cfg.clients);
1176-
jsonhandler->write_obj(cfg.requests > 0 ? "Requests per thread" : "Seconds","%u",
1177-
cfg.requests > 0 ? cfg.requests : cfg.test_time);
1176+
jsonhandler->write_obj(cfg.requests > 0 ? "Requests per thread" : "Seconds","%llu",
1177+
cfg.requests > 0 ? cfg.requests : (unsigned long long)cfg.test_time);
11781178
jsonhandler->close_nesting();
11791179
}
11801180

memtier_benchmark.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ struct benchmark_config {
4646
int distinct_client_seed;
4747
int randomize;
4848
int next_client_idx;
49-
unsigned int requests;
49+
unsigned long long requests;
5050
unsigned int clients;
5151
unsigned int threads;
5252
unsigned int test_time;

obj_gen.cpp

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,31 +50,39 @@ void random_generator::set_seed(int seed)
5050
assert(ret == 0);
5151
#elif (defined HAVE_DRAND48)
5252
memset(&m_data_blob, 0, sizeof(m_data_blob));
53-
memcpy(&m_data_blob, &seed, MIN(sizeof(seed), sizeof(m_data_blob)));
53+
size_t seed_size = sizeof(seed); //get MIN size between seed and m_data_blob
54+
if (seed_size > sizeof(m_data_blob))
55+
seed_size = sizeof(m_data_blob);
56+
memcpy(&m_data_blob, &seed, seed_size);
5457
#endif
5558
}
5659

5760
unsigned long long random_generator::get_random()
5861
{
59-
int rn;
6062
unsigned long long llrn;
6163
#ifdef HAVE_RANDOM_R
62-
int ret = random_r(&m_data_blob, &rn);//max is RAND_MAX
64+
int32_t rn;
65+
// max is RAND_MAX, which is usually 2^31-1 (although can be as low as 2^16-1, which we ignore now)
66+
// this is fine, especially considering that random_r is a nonstandard glibc extension
67+
// it returns a positive int32_t, so either way the MSB is off
68+
int ret = random_r(&m_data_blob, &rn);
6369
assert(ret == 0);
64-
6570
llrn = rn;
66-
llrn = llrn << 32; // move to upper 32bits
71+
llrn = llrn << 31;
6772

68-
ret = random_r(&m_data_blob, &rn);//max is RAND_MAX
73+
ret = random_r(&m_data_blob, &rn);
6974
assert(ret == 0);
70-
llrn |= rn; // set lower 32bits
75+
llrn |= rn;
7176
#elif (defined HAVE_DRAND48)
72-
rn = nrand48(m_data_blob); // max is 1<<31
77+
long rn;
78+
// jrand48's range is -2^31..+2^31 (i.e. all 32 bits)
79+
rn = jrand48(m_data_blob);
7380
llrn = rn;
74-
llrn = llrn << 32; // move to upper 32bits
81+
llrn = llrn << 32;
7582

76-
rn = nrand48(m_data_blob); // max is 1<<31
77-
llrn |= rn; // set lower 32bits
83+
rn = jrand48(m_data_blob);
84+
llrn |= rn & 0xffffffff; // reset the sign extension bits of negative numbers
85+
llrn &= 0x8000000000000000; // avoid any trouble from sign mismatch and negative numbers
7886
#else
7987
#error no random function
8088
#endif
@@ -84,12 +92,9 @@ unsigned long long random_generator::get_random()
8492
unsigned long long random_generator::get_random_max() const
8593
{
8694
#ifdef HAVE_RANDOM_R
87-
unsigned long long rand_max = RAND_MAX;
88-
return (rand_max << 32) | RAND_MAX;
95+
return 0x3fffffffffffffff;//62 bits
8996
#elif (defined HAVE_DRAND48)
90-
return ((1<<31) << 32) | (1<<31);
91-
#else
92-
#error no random function
97+
return 0x7fffffffffffffff;//63 bits
9398
#endif
9499
}
95100

0 commit comments

Comments
 (0)