1515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <binder/Binder.h> 2515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <binder/IBinder.h> 3515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <binder/IPCThreadState.h> 4515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <binder/IServiceManager.h> 5515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <string> 6515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <cstring> 7515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <cstdlib> 8515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <cstdio> 9515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 10515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <iostream> 11515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <vector> 12515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <tuple> 13515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 14515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <unistd.h> 15515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#include <sys/wait.h> 16515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 17515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsusing namespace std; 18515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsusing namespace android; 19515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 20515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsenum BinderWorkerServiceCode { 21515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews BINDER_NOP = IBinder::FIRST_CALL_TRANSACTION, 22515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews}; 23515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 24515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews#define ASSERT_TRUE(cond) \ 25515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsdo { \ 26515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (!(cond)) {\ 27515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cerr << __func__ << ":" << __LINE__ << " condition:" << #cond << " failed\n" << endl; \ 28515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews exit(EXIT_FAILURE); \ 29515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } \ 30515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} while (0) 31515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 32515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsclass BinderWorkerService : public BBinder 33515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 34515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewspublic: 35515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews BinderWorkerService() {} 36515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ~BinderWorkerService() {} 37515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews virtual status_t onTransact(uint32_t code, 38515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews const Parcel& data, Parcel* reply, 39515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint32_t flags = 0) { 40515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews (void)flags; 41515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews (void)data; 42515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews (void)reply; 43515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews switch (code) { 44515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews case BINDER_NOP: 45515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return NO_ERROR; 46515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews default: 47515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return UNKNOWN_TRANSACTION; 48515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews }; 49515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 50515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews}; 51515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 52515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsclass Pipe { 53515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int m_readFd; 54515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int m_writeFd; 55515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Pipe(int readFd, int writeFd) : m_readFd{readFd}, m_writeFd{writeFd} {} 56515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Pipe(const Pipe &) = delete; 57515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Pipe& operator=(const Pipe &) = delete; 58515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Pipe& operator=(const Pipe &&) = delete; 59515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewspublic: 60515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Pipe(Pipe&& rval) noexcept { 61515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_readFd = rval.m_readFd; 62515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_writeFd = rval.m_writeFd; 63515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews rval.m_readFd = 0; 64515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews rval.m_writeFd = 0; 65515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 66515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ~Pipe() { 67515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (m_readFd) 68515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews close(m_readFd); 69515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (m_writeFd) 70515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews close(m_writeFd); 71515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 72515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews void signal() { 73515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews bool val = true; 74515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error = write(m_writeFd, &val, sizeof(val)); 75515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error >= 0); 76515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews }; 77515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews void wait() { 78515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews bool val = false; 79515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error = read(m_readFd, &val, sizeof(val)); 80515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error >= 0); 81515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 82515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews template <typename T> void send(const T& v) { 83515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error = write(m_writeFd, &v, sizeof(T)); 84515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error >= 0); 85515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 86515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews template <typename T> void recv(T& v) { 87515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error = read(m_readFd, &v, sizeof(T)); 88515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error >= 0); 89515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 90515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews static tuple<Pipe, Pipe> createPipePair() { 91515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int a[2]; 92515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int b[2]; 93515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 94515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error1 = pipe(a); 95515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int error2 = pipe(b); 96515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error1 >= 0); 97515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ASSERT_TRUE(error2 >= 0); 98515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 99515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1])); 100515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 101515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews}; 102515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 103515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsstatic const uint32_t num_buckets = 128; 104c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yangstatic uint64_t max_time_bucket = 50ull * 1000000; 105c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yangstatic uint64_t time_per_bucket = max_time_bucket / num_buckets; 106515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 107515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsstruct ProcResults { 108515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint64_t m_worst = 0; 109515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint32_t m_buckets[num_buckets] = {0}; 110515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint64_t m_transactions = 0; 111c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang uint64_t m_long_transactions = 0; 112515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint64_t m_total_time = 0; 113c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang uint64_t m_best = max_time_bucket; 114515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 115515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews void add_time(uint64_t time) { 116c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (time > max_time_bucket) { 117c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang m_long_transactions++; 118c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 119515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_buckets[min(time, max_time_bucket-1) / time_per_bucket] += 1; 120515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_best = min(time, m_best); 121515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_worst = max(time, m_worst); 122515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_transactions += 1; 123515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews m_total_time += time; 124515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 125515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews static ProcResults combine(const ProcResults& a, const ProcResults& b) { 126515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ProcResults ret; 127515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < num_buckets; i++) { 128515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ret.m_buckets[i] = a.m_buckets[i] + b.m_buckets[i]; 129515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 130515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ret.m_worst = max(a.m_worst, b.m_worst); 131515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ret.m_best = min(a.m_best, b.m_best); 132515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ret.m_transactions = a.m_transactions + b.m_transactions; 133c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang ret.m_long_transactions = a.m_long_transactions + b.m_long_transactions; 134515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ret.m_total_time = a.m_total_time + b.m_total_time; 135515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return ret; 136515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 137515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews void dump() { 138c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (m_long_transactions > 0) { 139c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << (double)m_long_transactions / m_transactions << "% of transactions took longer " 140c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang "than estimated max latency. Consider setting -m to be higher than " 141c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang << m_worst / 1000 << " microseconds" << endl; 142c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 143c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang 144515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews double best = (double)m_best / 1.0E6; 145515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews double worst = (double)m_worst / 1.0E6; 146515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews double average = (double)m_total_time / m_transactions / 1.0E6; 147515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "average:" << average << "ms worst:" << worst << "ms best:" << best << "ms" << endl; 148515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 149515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint64_t cur_total = 0; 150c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang float time_per_bucket_ms = time_per_bucket / 1.0E6; 151515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < num_buckets; i++) { 152515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews float cur_time = time_per_bucket_ms * i + 0.5f * time_per_bucket_ms; 153515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if ((cur_total < 0.5f * m_transactions) && (cur_total + m_buckets[i] >= 0.5f * m_transactions)) { 154515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "50%: " << cur_time << " "; 155515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 156515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if ((cur_total < 0.9f * m_transactions) && (cur_total + m_buckets[i] >= 0.9f * m_transactions)) { 157515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "90%: " << cur_time << " "; 158515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 159515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if ((cur_total < 0.95f * m_transactions) && (cur_total + m_buckets[i] >= 0.95f * m_transactions)) { 160515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "95%: " << cur_time << " "; 161515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 162515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if ((cur_total < 0.99f * m_transactions) && (cur_total + m_buckets[i] >= 0.99f * m_transactions)) { 163515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "99%: " << cur_time << " "; 164515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 165515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cur_total += m_buckets[i]; 166515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 167515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << endl; 168515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 169515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews}; 170515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 171515aa0b911aebb0bd4665bc0b61a693d6951e994Riley AndrewsString16 generateServiceName(int num) 172515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 173515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews char num_str[32]; 174515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews snprintf(num_str, sizeof(num_str), "%d", num); 175515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews String16 serviceName = String16("binderWorker") + String16(num_str); 176515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return serviceName; 177515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 178515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 179c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yangvoid worker_fx(int num, 180c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang int worker_count, 181c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang int iterations, 182c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang int payload_size, 183c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang bool cs_pair, 184c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang Pipe p) 185515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 186515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Create BinderWorkerService and for go. 187515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ProcessState::self()->startThreadPool(); 188515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews sp<IServiceManager> serviceMgr = defaultServiceManager(); 189515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews sp<BinderWorkerService> service = new BinderWorkerService; 190515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews serviceMgr->addService(generateServiceName(num), service); 191515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 192515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews srand(num); 193515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.signal(); 194515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.wait(); 195515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 19625e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos // If client/server pairs, then half the workers are 19725e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos // servers and half are clients 19825e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos int server_count = cs_pair ? worker_count / 2 : worker_count; 19925e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos 200515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Get references to other binder services. 201515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "Created BinderWorker" << num << endl; 202515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews (void)worker_count; 203515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews vector<sp<IBinder> > workers; 20425e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos for (int i = 0; i < server_count; i++) { 205515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (num == i) 206515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews continue; 207515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews workers.push_back(serviceMgr->getService(generateServiceName(i))); 208515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 209515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 21025e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos // Run the benchmark if client 211515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ProcResults results; 212515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews chrono::time_point<chrono::high_resolution_clock> start, end; 21325e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos for (int i = 0; (!cs_pair || num >= server_count) && i < iterations; i++) { 214515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews Parcel data, reply; 21525e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos int target = cs_pair ? num % server_count : rand() % workers.size(); 216c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang int sz = payload_size; 21725e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos 218c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang while (sz > sizeof(uint32_t)) { 219c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang data.writeInt32(0); 220c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang sz -= sizeof(uint32_t); 221c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 222515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews start = chrono::high_resolution_clock::now(); 223515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews status_t ret = workers[target]->transact(BINDER_NOP, data, &reply); 224515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews end = chrono::high_resolution_clock::now(); 225515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 226515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews uint64_t cur_time = uint64_t(chrono::duration_cast<chrono::nanoseconds>(end - start).count()); 227515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews results.add_time(cur_time); 228515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 229515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (ret != NO_ERROR) { 230515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "thread " << num << " failed " << ret << "i : " << i << endl; 231515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews exit(EXIT_FAILURE); 232515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 233515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 23425e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos 235515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Signal completion to master and wait. 236515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.signal(); 237515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.wait(); 238515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 239515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Send results to master and wait for go to exit. 240515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.send(results); 241515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews p.wait(); 242515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 243515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews exit(EXIT_SUCCESS); 244515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 245515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 24625e1ded18ca51db209f3b8c3e199b4945066ab0cTodd KjosPipe make_worker(int num, int iterations, int worker_count, int payload_size, bool cs_pair) 247515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 248515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews auto pipe_pair = Pipe::createPipePair(); 249515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews pid_t pid = fork(); 250515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (pid) { 251515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews /* parent */ 252515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return move(get<0>(pipe_pair)); 253515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } else { 254515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews /* child */ 25525e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos worker_fx(num, worker_count, iterations, payload_size, cs_pair, move(get<1>(pipe_pair))); 256515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews /* never get here */ 257515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return move(get<0>(pipe_pair)); 258515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 259515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 260515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 261515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 262515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsvoid wait_all(vector<Pipe>& v) 263515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 264515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < v.size(); i++) { 265515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews v[i].wait(); 266515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 267515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 268515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 269515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrewsvoid signal_all(vector<Pipe>& v) 270515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 271515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < v.size(); i++) { 272515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews v[i].signal(); 273515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 274515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 275515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 276c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yangvoid run_main(int iterations, 277c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang int workers, 278c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang int payload_size, 279c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang int cs_pair, 280c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang bool training_round=false) 281515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews{ 282515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews vector<Pipe> pipes; 283515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Create all the workers and wait for them to spawn. 284515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < workers; i++) { 28525e1ded18ca51db209f3b8c3e199b4945066ab0cTodd Kjos pipes.push_back(make_worker(i, iterations, workers, payload_size, cs_pair)); 286515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 287515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews wait_all(pipes); 288515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 289515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Run the workers and wait for completion. 290515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews chrono::time_point<chrono::high_resolution_clock> start, end; 291515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "waiting for workers to complete" << endl; 292515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews start = chrono::high_resolution_clock::now(); 293515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews signal_all(pipes); 294515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews wait_all(pipes); 295515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews end = chrono::high_resolution_clock::now(); 296515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 297515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Calculate overall throughput. 298515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews double iterations_per_sec = double(iterations * workers) / (chrono::duration_cast<chrono::nanoseconds>(end - start).count() / 1.0E9); 299515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "iterations per sec: " << iterations_per_sec << endl; 300515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 301515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Collect all results from the workers. 302515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "collecting results" << endl; 303515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews signal_all(pipes); 304515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ProcResults tot_results; 305515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < workers; i++) { 306515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews ProcResults tmp_results; 307515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews pipes[i].recv(tmp_results); 308515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews tot_results = ProcResults::combine(tot_results, tmp_results); 309515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 310515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews 311515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews // Kill all the workers. 312515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "killing workers" << endl; 313515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews signal_all(pipes); 314515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews for (int i = 0; i < workers; i++) { 315515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews int status; 316515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews wait(&status); 317515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews if (status != 0) { 318515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews cout << "nonzero child status" << status << endl; 319515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 320515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews } 321c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (training_round) { 322c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang // sets max_time_bucket to 2 * m_worst from the training round. 323c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang // Also needs to adjust time_per_bucket accordingly. 324c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang max_time_bucket = 2 * tot_results.m_worst; 325c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang time_per_bucket = max_time_bucket / num_buckets; 326c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << "Max latency during training: " << tot_results.m_worst / 1.0E6 << "ms" << endl; 327c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } else { 328c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang tot_results.dump(); 329c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 330c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang} 331c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang 332c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yangint main(int argc, char *argv[]) 333c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang{ 334c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang int workers = 2; 335c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang int iterations = 10000; 336c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang int payload_size = 0; 337c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang bool cs_pair = false; 338c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang bool training_round = false; 339c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang (void)argc; 340c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang (void)argv; 341c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang 342c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang // Parse arguments. 343c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang for (int i = 1; i < argc; i++) { 344c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (string(argv[i]) == "--help") { 345c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << "Usage: binderThroughputTest [OPTIONS]" << endl; 346c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << "\t-i N : Specify number of iterations." << endl; 347c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << "\t-m N : Specify expected max latency in microseconds." << endl; 348c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << "\t-p : Split workers into client/server pairs." << endl; 349c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << "\t-s N : Specify payload size." << endl; 350c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << "\t-t N : Run training round." << endl; 351c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << "\t-w N : Specify total number of workers." << endl; 352c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang return 0; 353c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 354c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (string(argv[i]) == "-w") { 355c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang workers = atoi(argv[i+1]); 356c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang i++; 357c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang continue; 358c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 359c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (string(argv[i]) == "-i") { 360c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang iterations = atoi(argv[i+1]); 361c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang i++; 362c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang continue; 363c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 364c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (string(argv[i]) == "-s") { 365c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang payload_size = atoi(argv[i+1]); 366c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang i++; 367c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 368c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (string(argv[i]) == "-p") { 369c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang // client/server pairs instead of spreading 370c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang // requests to all workers. If true, half 371c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang // the workers become clients and half servers 372c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cs_pair = true; 373c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 374c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (string(argv[i]) == "-t") { 375c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang // Run one training round before actually collecting data 376c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang // to get an approximation of max latency. 377c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang training_round = true; 378c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 379c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (string(argv[i]) == "-m") { 380c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang // Caller specified the max latency in microseconds. 381c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang // No need to run training round in this case. 382c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (atoi(argv[i+1]) > 0) { 383c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang max_time_bucket = strtoull(argv[i+1], (char **)NULL, 10) * 1000; 384c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang i++; 385c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } else { 386c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << "Max latency -m must be positive." << endl; 387c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang exit(EXIT_FAILURE); 388c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 389c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 390c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 391c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang 392c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang if (training_round) { 393c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << "Start training round" << endl; 394c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang run_main(iterations, workers, payload_size, cs_pair, training_round=true); 395c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang cout << "Completed training round" << endl << endl; 396c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang } 397c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang 398c88f8bb54a39902206e7353dcd1a12bb5f07ddb2Sherry Yang run_main(iterations, workers, payload_size, cs_pair); 399515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews return 0; 400515aa0b911aebb0bd4665bc0b61a693d6951e994Riley Andrews} 401