15 #include "hashtable.h"
17 //#define TEST_STRING_KEYS
19 static volatile int wait_;
20 static volatile int stop_;
21 static int num_threads_;
24 static int get_range_;
25 static int put_range_;
26 static size_t num_keys_;
27 static map_key_t *keys_ = NULL;
28 static int ops_[MAX_NUM_THREADS] = {};
30 #define FOO (1ULL << 20)
32 void *worker (void *arg) {
33 int tid = (int)(size_t)arg;
34 uint64_t s = nbd_rand_seed(tid);
35 int get_ops = 0, put_ops = 0, del_ops = 0;
37 // Wait for all the worker threads to be ready.
38 (void)SYNC_ADD(&wait_, -1);
42 map_key_t key = keys_[ nbd_next_rand(&s) & (num_keys_ - 1) ];
43 uint32_t x = nbd_next_rand(&s) & (FOO - 1);
49 #ifdef TEST_STRING_KEYS
50 ASSERT(val == DOES_NOT_EXIST || ns_cmp((nstring_t *)key, (nstring_t *)val) == 0);
52 ASSERT(val == DOES_NOT_EXIST || key == val);
55 } else if (x < put_range_) {
56 map_add(map_, key, key);
59 map_remove(map_, key);
65 ops_[tid] = get_ops + put_ops + del_ops;
72 wait_ = num_threads_ + 1;
74 // Quicky sanity check
76 if (num_keys_ < n) { n = num_keys_; }
77 for (int i = 0; i < n; ++i) {
78 map_set(map_, keys_[i], keys_[i]);
79 for(int j = 0; j < i; ++j) {
80 #ifdef TEST_STRING_KEYS
81 ASSERT(ns_cmp((nstring_t *)map_get(map_, keys_[i]), (nstring_t *)keys_[i]) == 0);
83 ASSERT(map_get(map_, keys_[i]) == keys_[i]);
90 pthread_t thread[MAX_NUM_THREADS];
91 for (int i = 0; i < num_threads_; ++i) {
92 int rc = nbd_thread_create(thread + i, i, worker, (void*)(size_t)i);
93 if (rc != 0) { perror("pthread_create"); exit(rc); }
96 do { /* nothing */ } while (wait_ != 1);
102 for (int i = 0; i < num_threads_; ++i) {
103 pthread_join(thread[i], NULL);
106 for (int i = 0; i < num_threads_; ++i) {
112 int main (int argc, char **argv) {
113 char* program_name = argv[0];
116 fprintf(stderr, "Usage: %s num_threads\n", program_name);
124 num_threads_ = strtol(argv[1], NULL, 10);
126 fprintf(stderr, "%s: Invalid argument for number of threads\n", program_name);
129 if (num_threads_ <= 0) {
130 fprintf(stderr, "%s: Number of threads must be at least 1\n", program_name);
133 if (num_threads_ > MAX_NUM_THREADS) {
134 fprintf(stderr, "%s: Number of threads cannot be more than %d\n", program_name, MAX_NUM_THREADS);
139 int table_scale = 12;
141 table_scale = strtol(argv[2], NULL, 10);
143 fprintf(stderr, "%s: Invalid argument for the scale of the collection\n", program_name);
146 table_scale = strtol(argv[2], NULL, 10);
147 if (table_scale < 0 || table_scale > 31) {
148 fprintf(stderr, "%s: The scale of the collection must be between 0 and 31\n", program_name);
156 get_range_ = (int)((double)FOO / 100 * read_ratio);
157 put_range_ = get_range_ + (int)(((double)FOO - get_range_) / 100 * put_ratio);
159 static const map_impl_t *map_types[] = { &MAP_IMPL_SL };
160 for (int i = 0; i < sizeof(map_types)/sizeof(*map_types); ++i) {
161 #ifdef TEST_STRING_KEYS
162 map_ = map_alloc(map_types[i], &DATATYPE_NSTRING);
164 map_ = map_alloc(map_types[i], NULL);
168 num_keys_ = 1ULL << table_scale;
169 keys_ = nbd_malloc(sizeof(map_key_t) * num_keys_);
170 ASSERT(keys_ != NULL);
171 for (uint64_t j = 0; j < num_keys_; ++j) {
172 #ifdef TEST_STRING_KEYS
174 snprintf(tmp, sizeof(tmp), "%dabc%d", j, j*17+123);
176 keys_[j] = ns_alloc(n);
177 memcpy(keys_[j], tmp, n);
186 for (int i = 0; i < num_trials; ++i) {
189 double ops_per_sec = ops / num_trials / duration_;
192 printf("Threads:%-2d Size:2^%-2d Mops/Sec:%-4.3g per-thread:%-4.3g\n\n",
193 num_threads_, table_scale, ops_per_sec/1000000, ops_per_sec/num_threads_/1000000);