Tervel  1.0.0
A collection of wait-free containers and algorithms.
testObject.h
Go to the documentation of this file.
1 /*
2 #The MIT License (MIT)
3 #
4 #Copyright (c) 2015 University of Central Florida's Computer Software Engineering
5 #Scalable & Secure Systems (CSE - S3) Lab
6 #
7 #Permission is hereby granted, free of charge, to any person obtaining a copy
8 #of this software and associated documentation files (the "Software"), to deal
9 #in the Software without restriction, including without limitation the rights
10 #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 #copies of the Software, and to permit persons to whom the Software is
12 #furnished to do so, subject to the following conditions:
13 #
14 #The above copyright notice and this permission notice shall be included in
15 #all copies or substantial portions of the Software.
16 #
17 #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 #THE SOFTWARE.
24 #
25 */
26 
27 #include <climits>
28 #include <assert.h>
29 #include <atomic>
30 #include <random>
31 #include <string>
32 #include <cstdint>
33 #include <stdio.h>
34 #include <iostream>
35 #include <gflags/gflags.h>
36 
39 
42 // Constructor Arguments
43 DEFINE_int32(capacity, 64, "The initial capacity of the hash map");
44 
45 // Operation Rates
46 
47 DEFINE_int32(prefill, 0, "The number of elements to be initially inserted.");
48 DEFINE_int32(insert_rate, 25, "The percent of insert operations.");
49 DEFINE_int32(find_rate, 25, "The percent of find operations.");
50 DEFINE_int32(update_rate, 25, "The percent of update operations.");
51 DEFINE_int32(remove_rate, 25, "The percent of remove operations.");
52 
54 DEFINE_int32(num_threads, 1, "The number of executing threads.");
55 DEFINE_int32(execution_time, 5, "The amount of time to run the tests");
56 
57 
58 
59 typedef uint64_t Value;
60 class TestObject {
61  public:
62  enum op_codes : int { find = 0, insert, update, remove, LENGTH };
63  static const int k_num_functions = op_codes::LENGTH;
65  std::string* func_name_;
66 
67  std::atomic<int> func_call_count_[k_num_functions];
68  void set_rates() {
69  func_call_rate_ = new int[k_num_functions];
70  func_name_ = new std::string[k_num_functions];
71  #define MACRO_ADD_RATE(TervelOpName) \
72  func_name_[op_codes::TervelOpName] = "" #TervelOpName ; \
73  func_call_rate_[op_codes::TervelOpName] = FLAGS_##TervelOpName##_rate;
74 
78  MACRO_ADD_RATE(remove)
79 
80  for (int i = 0; i < k_num_functions; i++) {
81  func_call_count_[i].store(0);
82  }
83  };
84 
86  : num_threads_(FLAGS_num_threads)
87  , execution_time_(FLAGS_execution_time) {
88  set_rates();
89 
90  test_class_ = new TestClass<Value, Value>(FLAGS_num_threads+1, FLAGS_capacity);
91  };
92 
94  delete test_class_;
95  };
96 
97  // Define these functions if the test object requires per thread actions
98  void attachThread(int threadID) {
100  };
101 
102  void detachThread(int threadID) {
104  };
105 
107  /* This function is useful for enabling a blocking operation to return*/
108  };
109 
110  void init() {
111  /* This function is useful if you need to pre-fill a data structure */
112  std::default_random_engine generator;
113  std::uniform_int_distribution<uint64_t> largeValue(0, UINT_MAX);
114  for (int i = 0; i < FLAGS_prefill; i++) {
115  uint64_t x = largeValue(generator) & (~0xF);
116  uint64_t y = largeValue(generator) & (~0xF);
117  test_class_->insert(x, y);
118  }
119  }
120  void destroy() {
121  delete test_class_;
122  };
123 
124  void run(int64_t thread_id) {
125  // Initial Setup
126  attachThread(thread_id);
127 
128  int lcount = 0;
129  int func_call_count[k_num_functions];
130  int func_call_rate[k_num_functions];
131  int max_rand = 0;
132  for (int i = 0; i < k_num_functions; i++) {
133  func_call_rate[i] = func_call_rate_[i] + max_rand;
134  max_rand = func_call_rate[i];
135  func_call_count[i] = 0;
136  }
137 
138  // Setup Random Number Generation
139  std::default_random_engine generator;
140  std::uniform_int_distribution<int> distribution(0, max_rand);
141  std::uniform_int_distribution<int> largeValue(0, UINT_MAX);
142 
143  // Wait for start signle
144  ready_count_.fetch_add(1);
145  while (wait_flag_.load());
146 
148  while (running_.load()) {
149  lcount++;
150  int op = distribution(generator);
151  uint64_t key = largeValue(generator) & (~0xF);
152  uint64_t temp = largeValue(generator) & (~0xF);
153 
154  if (op <= func_call_rate[op_codes::find]) {
155  test_class_->find(key, temp);
156 
157  func_call_count[op_codes::find]++;
158  } else if (op <= func_call_rate[op_codes::insert]) {
159  test_class_->insert(key, temp);
160 
161  func_call_count[op_codes::insert]++;
162  } else if (op <= func_call_rate[op_codes::update]) {
163  test_class_->find(key, temp);
164  test_class_->update(key, temp, temp+1000);
165 
166  func_call_count[op_codes::update]++;
167  } else if (op <= func_call_rate[op_codes::remove]) {
168 
169  test_class_->remove(key);
170  func_call_count[op_codes::remove]++;
171  } else {
172  assert(false);
173  }
174  }
175  ready_count_.fetch_add(1);
176 
177  add_results(func_call_count);
178  detachThread(thread_id);
179  };
180 
181  std::string toString() {
182  std::string res("");
183  res += "Test Handler Configuration\n";
184  res += "\tThreads:" + std::to_string(num_threads_) + "\n";
185  res += "\tExecution Time: " + std::to_string(execution_time_) + "\n";
186 
187  res += "\tOperation rates\n";
188  for (int i = 0; i < k_num_functions; i++) {
189  res += "\t\t" + func_name_[i] + ": ";
190  res += std::to_string(func_call_rate_[i]) + "\n";
191  }
192 
193  return res;
194  };
195 
196  std::string results() {
197  std::string res("");
198  res += "-- Test Results--\n";
199  res += this->toString() + "\n";
200 
201  res += "Test Class Configuration\n";
202  res += test_class_->toString() + "\n";
203 
204 
205  res += "Operation Counts\n";
206  int sum = 0;
207  for (int i = 0; i < k_num_functions; i++) {
208  res += "\t" + func_name_[i] + ": " +
209  std::to_string(func_call_count_[i].load()) + "\n";
210  sum += func_call_count_[i].load();
211  }
212  res += "Total Operations: " + std::to_string(sum) + "\n";
213  res += "Reported Size: " + std::to_string(test_class_->size()) + "\n";
214  return res;
215  }
216 
217  void add_results(int func_call_count[k_num_functions]) {
218  for (int i = 0; i < k_num_functions; i++) {
219  func_call_count_[i].fetch_add(func_call_count[i]);
220  }
221  }
222 
223  const int num_threads_;
224  const int execution_time_;
225 
227 
228  std::atomic<bool> wait_flag_{true};
229  std::atomic<bool> running_{true};
230  std::atomic<int> ready_count_{0};
231 };
std::atomic< bool > wait_flag_
Definition: testObject.h:232
TestClass< Value, Value > * test_class_
Definition: testObject.h:226
std::string results()
Definition: testObject.h:196
Definition: testObject.h:62
void destroy()
Definition: testObject.h:120
void detach_thread()
Definition: blank_api.h:43
TestObject()
Definition: testObject.h:85
void attachThread(int threadID)
Definition: testObject.h:98
std::atomic< bool > running_
Definition: testObject.h:229
void run(int64_t thread_id)
Definition: testObject.h:124
Definition: testObject.h:60
bool insert(Key key, Value value)
Definition: blank_api.h:48
std::string * func_name_
Definition: testObject.h:65
void detachThread(int threadID)
Definition: testObject.h:102
std::atomic< int > func_call_count_[k_num_functions]
Definition: testObject.h:67
DEFINE_int32(capacity, 64,"The initial capacity of the hash map")
Change this when including a new data structure.
std::atomic< int > ready_count_
Definition: testObject.h:230
void attach_thread()
Definition: blank_api.h:40
const int num_threads_
Definition: testObject.h:223
void add_results(int func_call_count[k_num_functions])
Definition: testObject.h:217
int * func_call_rate_
Definition: testObject.h:64
Definition: testObject.h:62
bool update(Key key, Value &value_expected, Value value_new)
Definition: blank_api.h:51
op_codes
Definition: testObject.h:62
uint64_t Value
Definition: testObject.h:59
bool remove(Key key)
Definition: blank_api.h:54
const int execution_time_
Definition: testObject.h:224
Definition: testObject.h:62
void init()
Definition: testObject.h:110
size_t size()
Definition: blank_api.h:57
bool find(Key key, Value &value)
Definition: blank_api.h:45
std::string toString()
Definition: testObject.h:181
static const int k_num_functions
Definition: testObject.h:63
#define MACRO_ADD_RATE(TervelOpName)
Definition: testObject.h:62
void set_rates()
Definition: testObject.h:68
~TestObject()
Definition: testObject.h:93
void extra_end_signal()
Definition: testObject.h:106
std::string toString()
Definition: blank_api.h:36