Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 1 | #include <binder/Binder.h> |
| 2 | #include <binder/IBinder.h> |
| 3 | #include <binder/IPCThreadState.h> |
| 4 | #include <binder/IServiceManager.h> |
| 5 | #include <string> |
| 6 | #include <cstring> |
| 7 | #include <cstdlib> |
| 8 | #include <cstdio> |
| 9 | |
| 10 | #include <iostream> |
| 11 | #include <vector> |
| 12 | #include <tuple> |
| 13 | |
| 14 | #include <unistd.h> |
| 15 | #include <sys/wait.h> |
| 16 | |
| 17 | using namespace std; |
| 18 | using namespace android; |
| 19 | |
| 20 | enum BinderWorkerServiceCode { |
| 21 | BINDER_NOP = IBinder::FIRST_CALL_TRANSACTION, |
| 22 | }; |
| 23 | |
| 24 | #define ASSERT_TRUE(cond) \ |
| 25 | do { \ |
| 26 | if (!(cond)) {\ |
| 27 | cerr << __func__ << ":" << __LINE__ << " condition:" << #cond << " failed\n" << endl; \ |
| 28 | exit(EXIT_FAILURE); \ |
| 29 | } \ |
| 30 | } while (0) |
| 31 | |
| 32 | class BinderWorkerService : public BBinder |
| 33 | { |
| 34 | public: |
| 35 | BinderWorkerService() {} |
| 36 | ~BinderWorkerService() {} |
| 37 | virtual status_t onTransact(uint32_t code, |
| 38 | const Parcel& data, Parcel* reply, |
| 39 | uint32_t flags = 0) { |
| 40 | (void)flags; |
| 41 | (void)data; |
| 42 | (void)reply; |
| 43 | switch (code) { |
| 44 | case BINDER_NOP: |
| 45 | return NO_ERROR; |
| 46 | default: |
| 47 | return UNKNOWN_TRANSACTION; |
| 48 | }; |
| 49 | } |
| 50 | }; |
| 51 | |
Alice Ryhl | 4d46cd8 | 2023-07-28 15:11:11 +0000 | [diff] [blame] | 52 | static uint64_t warn_latency = std::numeric_limits<uint64_t>::max(); |
| 53 | |
| 54 | struct ProcResults { |
| 55 | vector<uint64_t> data; |
| 56 | |
| 57 | ProcResults(size_t capacity) { data.reserve(capacity); } |
| 58 | |
| 59 | void add_time(uint64_t time) { data.push_back(time); } |
| 60 | void combine_with(const ProcResults& append) { |
| 61 | data.insert(data.end(), append.data.begin(), append.data.end()); |
| 62 | } |
| 63 | uint64_t worst() { |
| 64 | return *max_element(data.begin(), data.end()); |
| 65 | } |
| 66 | void dump() { |
| 67 | if (data.size() == 0) { |
| 68 | // This avoids index-out-of-bounds below. |
| 69 | cout << "error: no data\n" << endl; |
| 70 | return; |
| 71 | } |
| 72 | |
| 73 | size_t num_long_transactions = 0; |
| 74 | for (uint64_t elem : data) { |
| 75 | if (elem > warn_latency) { |
| 76 | num_long_transactions += 1; |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | if (num_long_transactions > 0) { |
| 81 | cout << (double)num_long_transactions / data.size() << "% of transactions took longer " |
| 82 | "than estimated max latency. Consider setting -m to be higher than " |
| 83 | << worst() / 1000 << " microseconds" << endl; |
| 84 | } |
| 85 | |
| 86 | sort(data.begin(), data.end()); |
| 87 | |
| 88 | uint64_t total_time = 0; |
| 89 | for (uint64_t elem : data) { |
| 90 | total_time += elem; |
| 91 | } |
| 92 | |
| 93 | double best = (double)data[0] / 1.0E6; |
| 94 | double worst = (double)data.back() / 1.0E6; |
| 95 | double average = (double)total_time / data.size() / 1.0E6; |
| 96 | cout << "average:" << average << "ms worst:" << worst << "ms best:" << best << "ms" << endl; |
| 97 | |
| 98 | double percentile_50 = data[(50 * data.size()) / 100] / 1.0E6; |
| 99 | double percentile_90 = data[(90 * data.size()) / 100] / 1.0E6; |
| 100 | double percentile_95 = data[(95 * data.size()) / 100] / 1.0E6; |
| 101 | double percentile_99 = data[(99 * data.size()) / 100] / 1.0E6; |
| 102 | cout << "50%: " << percentile_50 << " "; |
| 103 | cout << "90%: " << percentile_90 << " "; |
| 104 | cout << "95%: " << percentile_95 << " "; |
| 105 | cout << "99%: " << percentile_99 << endl; |
| 106 | } |
| 107 | }; |
| 108 | |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 109 | class Pipe { |
| 110 | int m_readFd; |
| 111 | int m_writeFd; |
| 112 | Pipe(int readFd, int writeFd) : m_readFd{readFd}, m_writeFd{writeFd} {} |
| 113 | Pipe(const Pipe &) = delete; |
| 114 | Pipe& operator=(const Pipe &) = delete; |
| 115 | Pipe& operator=(const Pipe &&) = delete; |
| 116 | public: |
| 117 | Pipe(Pipe&& rval) noexcept { |
| 118 | m_readFd = rval.m_readFd; |
| 119 | m_writeFd = rval.m_writeFd; |
| 120 | rval.m_readFd = 0; |
| 121 | rval.m_writeFd = 0; |
| 122 | } |
| 123 | ~Pipe() { |
| 124 | if (m_readFd) |
| 125 | close(m_readFd); |
| 126 | if (m_writeFd) |
| 127 | close(m_writeFd); |
| 128 | } |
| 129 | void signal() { |
| 130 | bool val = true; |
| 131 | int error = write(m_writeFd, &val, sizeof(val)); |
| 132 | ASSERT_TRUE(error >= 0); |
| 133 | }; |
| 134 | void wait() { |
| 135 | bool val = false; |
| 136 | int error = read(m_readFd, &val, sizeof(val)); |
| 137 | ASSERT_TRUE(error >= 0); |
| 138 | } |
Alice Ryhl | 4d46cd8 | 2023-07-28 15:11:11 +0000 | [diff] [blame] | 139 | void send(const ProcResults& v) { |
| 140 | size_t num_elems = v.data.size(); |
| 141 | |
| 142 | int error = write(m_writeFd, &num_elems, sizeof(size_t)); |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 143 | ASSERT_TRUE(error >= 0); |
Alice Ryhl | 4d46cd8 | 2023-07-28 15:11:11 +0000 | [diff] [blame] | 144 | |
| 145 | char* to_write = (char*)v.data.data(); |
| 146 | size_t num_bytes = sizeof(uint64_t) * num_elems; |
| 147 | |
| 148 | while (num_bytes > 0) { |
| 149 | int ret = write(m_writeFd, to_write, num_bytes); |
| 150 | ASSERT_TRUE(ret >= 0); |
| 151 | num_bytes -= ret; |
| 152 | to_write += ret; |
| 153 | } |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 154 | } |
Alice Ryhl | 4d46cd8 | 2023-07-28 15:11:11 +0000 | [diff] [blame] | 155 | void recv(ProcResults& v) { |
| 156 | size_t num_elems = 0; |
| 157 | int error = read(m_readFd, &num_elems, sizeof(size_t)); |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 158 | ASSERT_TRUE(error >= 0); |
Alice Ryhl | 4d46cd8 | 2023-07-28 15:11:11 +0000 | [diff] [blame] | 159 | |
| 160 | v.data.resize(num_elems); |
| 161 | char* read_to = (char*)v.data.data(); |
| 162 | size_t num_bytes = sizeof(uint64_t) * num_elems; |
| 163 | |
| 164 | while (num_bytes > 0) { |
| 165 | int ret = read(m_readFd, read_to, num_bytes); |
| 166 | ASSERT_TRUE(ret >= 0); |
| 167 | num_bytes -= ret; |
| 168 | read_to += ret; |
| 169 | } |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 170 | } |
| 171 | static tuple<Pipe, Pipe> createPipePair() { |
| 172 | int a[2]; |
| 173 | int b[2]; |
| 174 | |
| 175 | int error1 = pipe(a); |
| 176 | int error2 = pipe(b); |
| 177 | ASSERT_TRUE(error1 >= 0); |
| 178 | ASSERT_TRUE(error2 >= 0); |
| 179 | |
| 180 | return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1])); |
| 181 | } |
| 182 | }; |
| 183 | |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 184 | String16 generateServiceName(int num) |
| 185 | { |
| 186 | char num_str[32]; |
| 187 | snprintf(num_str, sizeof(num_str), "%d", num); |
| 188 | String16 serviceName = String16("binderWorker") + String16(num_str); |
| 189 | return serviceName; |
| 190 | } |
| 191 | |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 192 | void worker_fx(int num, |
| 193 | int worker_count, |
| 194 | int iterations, |
| 195 | int payload_size, |
| 196 | bool cs_pair, |
| 197 | Pipe p) |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 198 | { |
| 199 | // Create BinderWorkerService and for go. |
| 200 | ProcessState::self()->startThreadPool(); |
| 201 | sp<IServiceManager> serviceMgr = defaultServiceManager(); |
| 202 | sp<BinderWorkerService> service = new BinderWorkerService; |
| 203 | serviceMgr->addService(generateServiceName(num), service); |
| 204 | |
| 205 | srand(num); |
| 206 | p.signal(); |
| 207 | p.wait(); |
| 208 | |
Todd Kjos | abd8883 | 2016-11-22 16:46:36 -0800 | [diff] [blame] | 209 | // If client/server pairs, then half the workers are |
| 210 | // servers and half are clients |
| 211 | int server_count = cs_pair ? worker_count / 2 : worker_count; |
| 212 | |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 213 | // Get references to other binder services. |
| 214 | cout << "Created BinderWorker" << num << endl; |
| 215 | (void)worker_count; |
| 216 | vector<sp<IBinder> > workers; |
Todd Kjos | abd8883 | 2016-11-22 16:46:36 -0800 | [diff] [blame] | 217 | for (int i = 0; i < server_count; i++) { |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 218 | if (num == i) |
| 219 | continue; |
Carlos Llamas | 8c51352 | 2023-09-23 20:24:20 +0000 | [diff] [blame] | 220 | workers.push_back(serviceMgr->waitForService(generateServiceName(i))); |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 221 | } |
| 222 | |
Todd Kjos | abd8883 | 2016-11-22 16:46:36 -0800 | [diff] [blame] | 223 | // Run the benchmark if client |
Alice Ryhl | 4d46cd8 | 2023-07-28 15:11:11 +0000 | [diff] [blame] | 224 | ProcResults results(iterations); |
| 225 | |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 226 | chrono::time_point<chrono::high_resolution_clock> start, end; |
Todd Kjos | abd8883 | 2016-11-22 16:46:36 -0800 | [diff] [blame] | 227 | for (int i = 0; (!cs_pair || num >= server_count) && i < iterations; i++) { |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 228 | Parcel data, reply; |
Todd Kjos | abd8883 | 2016-11-22 16:46:36 -0800 | [diff] [blame] | 229 | int target = cs_pair ? num % server_count : rand() % workers.size(); |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 230 | int sz = payload_size; |
Todd Kjos | abd8883 | 2016-11-22 16:46:36 -0800 | [diff] [blame] | 231 | |
Todd Kjos | e61c9b1 | 2017-10-03 14:04:39 -0700 | [diff] [blame] | 232 | while (sz >= sizeof(uint32_t)) { |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 233 | data.writeInt32(0); |
| 234 | sz -= sizeof(uint32_t); |
| 235 | } |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 236 | start = chrono::high_resolution_clock::now(); |
| 237 | status_t ret = workers[target]->transact(BINDER_NOP, data, &reply); |
| 238 | end = chrono::high_resolution_clock::now(); |
| 239 | |
| 240 | uint64_t cur_time = uint64_t(chrono::duration_cast<chrono::nanoseconds>(end - start).count()); |
| 241 | results.add_time(cur_time); |
| 242 | |
| 243 | if (ret != NO_ERROR) { |
| 244 | cout << "thread " << num << " failed " << ret << "i : " << i << endl; |
| 245 | exit(EXIT_FAILURE); |
| 246 | } |
| 247 | } |
Todd Kjos | abd8883 | 2016-11-22 16:46:36 -0800 | [diff] [blame] | 248 | |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 249 | // Signal completion to master and wait. |
| 250 | p.signal(); |
| 251 | p.wait(); |
| 252 | |
| 253 | // Send results to master and wait for go to exit. |
| 254 | p.send(results); |
| 255 | p.wait(); |
| 256 | |
| 257 | exit(EXIT_SUCCESS); |
| 258 | } |
| 259 | |
Todd Kjos | abd8883 | 2016-11-22 16:46:36 -0800 | [diff] [blame] | 260 | Pipe make_worker(int num, int iterations, int worker_count, int payload_size, bool cs_pair) |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 261 | { |
| 262 | auto pipe_pair = Pipe::createPipePair(); |
| 263 | pid_t pid = fork(); |
| 264 | if (pid) { |
| 265 | /* parent */ |
Yi Kong | 5436a87 | 2022-08-03 14:40:29 +0800 | [diff] [blame] | 266 | return std::move(get<0>(pipe_pair)); |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 267 | } else { |
| 268 | /* child */ |
Yi Kong | 5436a87 | 2022-08-03 14:40:29 +0800 | [diff] [blame] | 269 | worker_fx(num, worker_count, iterations, payload_size, cs_pair, |
| 270 | std::move(get<1>(pipe_pair))); |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 271 | /* never get here */ |
Yi Kong | 5436a87 | 2022-08-03 14:40:29 +0800 | [diff] [blame] | 272 | return std::move(get<0>(pipe_pair)); |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 273 | } |
| 274 | |
| 275 | } |
| 276 | |
| 277 | void wait_all(vector<Pipe>& v) |
| 278 | { |
| 279 | for (int i = 0; i < v.size(); i++) { |
| 280 | v[i].wait(); |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | void signal_all(vector<Pipe>& v) |
| 285 | { |
| 286 | for (int i = 0; i < v.size(); i++) { |
| 287 | v[i].signal(); |
| 288 | } |
| 289 | } |
| 290 | |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 291 | void run_main(int iterations, |
| 292 | int workers, |
| 293 | int payload_size, |
| 294 | int cs_pair, |
| 295 | bool training_round=false) |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 296 | { |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 297 | vector<Pipe> pipes; |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 298 | // Create all the workers and wait for them to spawn. |
| 299 | for (int i = 0; i < workers; i++) { |
Todd Kjos | abd8883 | 2016-11-22 16:46:36 -0800 | [diff] [blame] | 300 | pipes.push_back(make_worker(i, iterations, workers, payload_size, cs_pair)); |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 301 | } |
| 302 | wait_all(pipes); |
| 303 | |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 304 | // Run the workers and wait for completion. |
| 305 | chrono::time_point<chrono::high_resolution_clock> start, end; |
| 306 | cout << "waiting for workers to complete" << endl; |
| 307 | start = chrono::high_resolution_clock::now(); |
| 308 | signal_all(pipes); |
| 309 | wait_all(pipes); |
| 310 | end = chrono::high_resolution_clock::now(); |
| 311 | |
| 312 | // Calculate overall throughput. |
| 313 | double iterations_per_sec = double(iterations * workers) / (chrono::duration_cast<chrono::nanoseconds>(end - start).count() / 1.0E9); |
| 314 | cout << "iterations per sec: " << iterations_per_sec << endl; |
| 315 | |
| 316 | // Collect all results from the workers. |
| 317 | cout << "collecting results" << endl; |
| 318 | signal_all(pipes); |
Alice Ryhl | 4d46cd8 | 2023-07-28 15:11:11 +0000 | [diff] [blame] | 319 | ProcResults tot_results(0), tmp_results(0); |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 320 | for (int i = 0; i < workers; i++) { |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 321 | pipes[i].recv(tmp_results); |
Alice Ryhl | 4d46cd8 | 2023-07-28 15:11:11 +0000 | [diff] [blame] | 322 | tot_results.combine_with(tmp_results); |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 323 | } |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 324 | |
| 325 | // Kill all the workers. |
| 326 | cout << "killing workers" << endl; |
| 327 | signal_all(pipes); |
| 328 | for (int i = 0; i < workers; i++) { |
| 329 | int status; |
| 330 | wait(&status); |
| 331 | if (status != 0) { |
| 332 | cout << "nonzero child status" << status << endl; |
| 333 | } |
| 334 | } |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 335 | if (training_round) { |
Alice Ryhl | 4d46cd8 | 2023-07-28 15:11:11 +0000 | [diff] [blame] | 336 | // Sets warn_latency to 2 * worst from the training round. |
| 337 | warn_latency = 2 * tot_results.worst(); |
| 338 | cout << "Max latency during training: " << tot_results.worst() / 1.0E6 << "ms" << endl; |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 339 | } else { |
Alice Ryhl | 4d46cd8 | 2023-07-28 15:11:11 +0000 | [diff] [blame] | 340 | tot_results.dump(); |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 341 | } |
| 342 | } |
| 343 | |
| 344 | int main(int argc, char *argv[]) |
| 345 | { |
| 346 | int workers = 2; |
| 347 | int iterations = 10000; |
| 348 | int payload_size = 0; |
| 349 | bool cs_pair = false; |
| 350 | bool training_round = false; |
Carlos Llamas | 9a85d30 | 2023-09-23 22:41:22 +0000 | [diff] [blame] | 351 | int max_time_us; |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 352 | |
| 353 | // Parse arguments. |
| 354 | for (int i = 1; i < argc; i++) { |
| 355 | if (string(argv[i]) == "--help") { |
| 356 | cout << "Usage: binderThroughputTest [OPTIONS]" << endl; |
| 357 | cout << "\t-i N : Specify number of iterations." << endl; |
| 358 | cout << "\t-m N : Specify expected max latency in microseconds." << endl; |
| 359 | cout << "\t-p : Split workers into client/server pairs." << endl; |
| 360 | cout << "\t-s N : Specify payload size." << endl; |
Carlos Llamas | b21d7fd | 2023-09-23 21:20:51 +0000 | [diff] [blame] | 361 | cout << "\t-t : Run training round." << endl; |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 362 | cout << "\t-w N : Specify total number of workers." << endl; |
| 363 | return 0; |
| 364 | } |
| 365 | if (string(argv[i]) == "-w") { |
Alice Ryhl | b39f05a | 2024-01-05 13:10:12 +0000 | [diff] [blame] | 366 | if (i + 1 == argc) { |
| 367 | cout << "-w requires an argument\n" << endl; |
| 368 | exit(EXIT_FAILURE); |
| 369 | } |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 370 | workers = atoi(argv[i+1]); |
| 371 | i++; |
| 372 | continue; |
| 373 | } |
| 374 | if (string(argv[i]) == "-i") { |
Alice Ryhl | b39f05a | 2024-01-05 13:10:12 +0000 | [diff] [blame] | 375 | if (i + 1 == argc) { |
| 376 | cout << "-i requires an argument\n" << endl; |
| 377 | exit(EXIT_FAILURE); |
| 378 | } |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 379 | iterations = atoi(argv[i+1]); |
| 380 | i++; |
| 381 | continue; |
| 382 | } |
| 383 | if (string(argv[i]) == "-s") { |
Alice Ryhl | b39f05a | 2024-01-05 13:10:12 +0000 | [diff] [blame] | 384 | if (i + 1 == argc) { |
| 385 | cout << "-s requires an argument\n" << endl; |
| 386 | exit(EXIT_FAILURE); |
| 387 | } |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 388 | payload_size = atoi(argv[i+1]); |
| 389 | i++; |
Carlos Llamas | 71686da | 2023-09-23 20:34:58 +0000 | [diff] [blame] | 390 | continue; |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 391 | } |
| 392 | if (string(argv[i]) == "-p") { |
| 393 | // client/server pairs instead of spreading |
| 394 | // requests to all workers. If true, half |
| 395 | // the workers become clients and half servers |
| 396 | cs_pair = true; |
Carlos Llamas | 71686da | 2023-09-23 20:34:58 +0000 | [diff] [blame] | 397 | continue; |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 398 | } |
| 399 | if (string(argv[i]) == "-t") { |
| 400 | // Run one training round before actually collecting data |
| 401 | // to get an approximation of max latency. |
| 402 | training_round = true; |
Carlos Llamas | 71686da | 2023-09-23 20:34:58 +0000 | [diff] [blame] | 403 | continue; |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 404 | } |
| 405 | if (string(argv[i]) == "-m") { |
Alice Ryhl | b39f05a | 2024-01-05 13:10:12 +0000 | [diff] [blame] | 406 | if (i + 1 == argc) { |
| 407 | cout << "-m requires an argument\n" << endl; |
| 408 | exit(EXIT_FAILURE); |
| 409 | } |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 410 | // Caller specified the max latency in microseconds. |
| 411 | // No need to run training round in this case. |
Carlos Llamas | 9a85d30 | 2023-09-23 22:41:22 +0000 | [diff] [blame] | 412 | max_time_us = atoi(argv[i+1]); |
| 413 | if (max_time_us <= 0) { |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 414 | cout << "Max latency -m must be positive." << endl; |
| 415 | exit(EXIT_FAILURE); |
| 416 | } |
Alice Ryhl | 4d46cd8 | 2023-07-28 15:11:11 +0000 | [diff] [blame] | 417 | warn_latency = max_time_us * 1000ull; |
Carlos Llamas | 9a85d30 | 2023-09-23 22:41:22 +0000 | [diff] [blame] | 418 | i++; |
Carlos Llamas | 71686da | 2023-09-23 20:34:58 +0000 | [diff] [blame] | 419 | continue; |
Sherry Yang | 52d1540 | 2017-06-15 11:32:06 -0700 | [diff] [blame] | 420 | } |
| 421 | } |
| 422 | |
| 423 | if (training_round) { |
| 424 | cout << "Start training round" << endl; |
| 425 | run_main(iterations, workers, payload_size, cs_pair, training_round=true); |
| 426 | cout << "Completed training round" << endl << endl; |
| 427 | } |
| 428 | |
| 429 | run_main(iterations, workers, payload_size, cs_pair); |
Riley Andrews | 515aa0b | 2015-08-11 13:19:53 -0700 | [diff] [blame] | 430 | return 0; |
| 431 | } |