xref: /aosp_15_r20/system/libhwbinder/vts/performance/Benchmark_throughput.cpp (revision 77b80299c8bdfeca3ae6d0ce27ae1ad3db289be3)
1*77b80299SAndroid Build Coastguard Worker /*
2*77b80299SAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*77b80299SAndroid Build Coastguard Worker  *
4*77b80299SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*77b80299SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*77b80299SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*77b80299SAndroid Build Coastguard Worker  *
8*77b80299SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*77b80299SAndroid Build Coastguard Worker  *
10*77b80299SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*77b80299SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*77b80299SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*77b80299SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*77b80299SAndroid Build Coastguard Worker  * limitations under the License.
15*77b80299SAndroid Build Coastguard Worker  */
16*77b80299SAndroid Build Coastguard Worker #define LOG_TAG "HwbinderThroughputTest"
17*77b80299SAndroid Build Coastguard Worker 
18*77b80299SAndroid Build Coastguard Worker #include <unistd.h>
19*77b80299SAndroid Build Coastguard Worker #include <sys/wait.h>
20*77b80299SAndroid Build Coastguard Worker 
21*77b80299SAndroid Build Coastguard Worker #include <cstring>
22*77b80299SAndroid Build Coastguard Worker #include <iostream>
23*77b80299SAndroid Build Coastguard Worker #include <string>
24*77b80299SAndroid Build Coastguard Worker #include <tuple>
25*77b80299SAndroid Build Coastguard Worker #include <vector>
26*77b80299SAndroid Build Coastguard Worker 
27*77b80299SAndroid Build Coastguard Worker #include <log/log.h>
28*77b80299SAndroid Build Coastguard Worker 
29*77b80299SAndroid Build Coastguard Worker #include <android/hardware/tests/libhwbinder/1.0/IBenchmark.h>
30*77b80299SAndroid Build Coastguard Worker #include <hidl/HidlSupport.h>
31*77b80299SAndroid Build Coastguard Worker #include <hidl/ServiceManagement.h>
32*77b80299SAndroid Build Coastguard Worker 
33*77b80299SAndroid Build Coastguard Worker using namespace std;
34*77b80299SAndroid Build Coastguard Worker using namespace android;
35*77b80299SAndroid Build Coastguard Worker using namespace android::hardware;
36*77b80299SAndroid Build Coastguard Worker 
37*77b80299SAndroid Build Coastguard Worker // Generated HIDL files
38*77b80299SAndroid Build Coastguard Worker using android::hardware::tests::libhwbinder::V1_0::IBenchmark;
39*77b80299SAndroid Build Coastguard Worker 
40*77b80299SAndroid Build Coastguard Worker #define ASSERT_TRUE(cond) \
41*77b80299SAndroid Build Coastguard Worker do { \
42*77b80299SAndroid Build Coastguard Worker     if (!(cond)) {\
43*77b80299SAndroid Build Coastguard Worker        cerr << __func__ << ":" << __LINE__ << " condition:" << #cond << " failed\n" << endl; \
44*77b80299SAndroid Build Coastguard Worker        exit(EXIT_FAILURE); \
45*77b80299SAndroid Build Coastguard Worker     } \
46*77b80299SAndroid Build Coastguard Worker } while (0)
47*77b80299SAndroid Build Coastguard Worker 
48*77b80299SAndroid Build Coastguard Worker class Pipe {
49*77b80299SAndroid Build Coastguard Worker     int m_readFd;
50*77b80299SAndroid Build Coastguard Worker     int m_writeFd;
Pipe(int readFd,int writeFd)51*77b80299SAndroid Build Coastguard Worker     Pipe(int readFd, int writeFd)
52*77b80299SAndroid Build Coastguard Worker             : m_readFd{readFd}, m_writeFd{writeFd} {
53*77b80299SAndroid Build Coastguard Worker     }
54*77b80299SAndroid Build Coastguard Worker     Pipe(const Pipe &) = delete;
55*77b80299SAndroid Build Coastguard Worker     Pipe& operator=(const Pipe &) = delete;
56*77b80299SAndroid Build Coastguard Worker     Pipe& operator=(const Pipe &&) = delete;
57*77b80299SAndroid Build Coastguard Worker  public:
Pipe(Pipe && rval)58*77b80299SAndroid Build Coastguard Worker     Pipe(Pipe&& rval) noexcept {
59*77b80299SAndroid Build Coastguard Worker         m_readFd = rval.m_readFd;
60*77b80299SAndroid Build Coastguard Worker         m_writeFd = rval.m_writeFd;
61*77b80299SAndroid Build Coastguard Worker         rval.m_readFd = 0;
62*77b80299SAndroid Build Coastguard Worker         rval.m_writeFd = 0;
63*77b80299SAndroid Build Coastguard Worker     }
~Pipe()64*77b80299SAndroid Build Coastguard Worker     ~Pipe() {
65*77b80299SAndroid Build Coastguard Worker         if (m_readFd)
66*77b80299SAndroid Build Coastguard Worker             close(m_readFd);
67*77b80299SAndroid Build Coastguard Worker         if (m_writeFd)
68*77b80299SAndroid Build Coastguard Worker             close(m_writeFd);
69*77b80299SAndroid Build Coastguard Worker     }
signal()70*77b80299SAndroid Build Coastguard Worker     void signal() {
71*77b80299SAndroid Build Coastguard Worker         bool val = true;
72*77b80299SAndroid Build Coastguard Worker         int error = write(m_writeFd, &val, sizeof(val));
73*77b80299SAndroid Build Coastguard Worker         ASSERT_TRUE(error >= 0);
74*77b80299SAndroid Build Coastguard Worker     }
wait()75*77b80299SAndroid Build Coastguard Worker     void wait() {
76*77b80299SAndroid Build Coastguard Worker         bool val = false;
77*77b80299SAndroid Build Coastguard Worker         int error = read(m_readFd, &val, sizeof(val));
78*77b80299SAndroid Build Coastguard Worker         ASSERT_TRUE(error >= 0);
79*77b80299SAndroid Build Coastguard Worker     }
send(const T & v)80*77b80299SAndroid Build Coastguard Worker     template<typename T> void send(const T& v) {
81*77b80299SAndroid Build Coastguard Worker         int error = write(m_writeFd, &v, sizeof(T));
82*77b80299SAndroid Build Coastguard Worker         ASSERT_TRUE(error >= 0);
83*77b80299SAndroid Build Coastguard Worker     }
recv(T & v)84*77b80299SAndroid Build Coastguard Worker     template<typename T> void recv(T& v) {
85*77b80299SAndroid Build Coastguard Worker         int error = read(m_readFd, &v, sizeof(T));
86*77b80299SAndroid Build Coastguard Worker         ASSERT_TRUE(error >= 0);
87*77b80299SAndroid Build Coastguard Worker     }
createPipePair()88*77b80299SAndroid Build Coastguard Worker     static tuple<Pipe, Pipe> createPipePair() {
89*77b80299SAndroid Build Coastguard Worker         int a[2];
90*77b80299SAndroid Build Coastguard Worker         int b[2];
91*77b80299SAndroid Build Coastguard Worker 
92*77b80299SAndroid Build Coastguard Worker         int error1 = pipe(a);
93*77b80299SAndroid Build Coastguard Worker         int error2 = pipe(b);
94*77b80299SAndroid Build Coastguard Worker         ASSERT_TRUE(error1 >= 0);
95*77b80299SAndroid Build Coastguard Worker         ASSERT_TRUE(error2 >= 0);
96*77b80299SAndroid Build Coastguard Worker 
97*77b80299SAndroid Build Coastguard Worker         return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1]));
98*77b80299SAndroid Build Coastguard Worker     }
99*77b80299SAndroid Build Coastguard Worker };
100*77b80299SAndroid Build Coastguard Worker 
101*77b80299SAndroid Build Coastguard Worker static const uint32_t num_buckets = 128;
102*77b80299SAndroid Build Coastguard Worker static const uint64_t max_time_bucket = 50ull * 1000000;
103*77b80299SAndroid Build Coastguard Worker static const uint64_t time_per_bucket = max_time_bucket / num_buckets;
104*77b80299SAndroid Build Coastguard Worker static constexpr float time_per_bucket_ms = time_per_bucket / 1.0E6;
105*77b80299SAndroid Build Coastguard Worker 
106*77b80299SAndroid Build Coastguard Worker struct ProcResults {
107*77b80299SAndroid Build Coastguard Worker     uint64_t m_best = max_time_bucket;
108*77b80299SAndroid Build Coastguard Worker     uint64_t m_worst = 0;
109*77b80299SAndroid Build Coastguard Worker     uint32_t m_buckets[num_buckets] = {0};
110*77b80299SAndroid Build Coastguard Worker     uint64_t m_transactions = 0;
111*77b80299SAndroid Build Coastguard Worker     uint64_t m_total_time = 0;
112*77b80299SAndroid Build Coastguard Worker 
113*77b80299SAndroid Build Coastguard Worker     // Add a new latency data point and update the aggregation info
114*77b80299SAndroid Build Coastguard Worker     // e.g. best/worst/total_time.
add_timeProcResults115*77b80299SAndroid Build Coastguard Worker     void add_time(uint64_t time) {
116*77b80299SAndroid Build Coastguard Worker         m_buckets[min(time, max_time_bucket - 1) / time_per_bucket] += 1;
117*77b80299SAndroid Build Coastguard Worker         m_best = min(time, m_best);
118*77b80299SAndroid Build Coastguard Worker         m_worst = max(time, m_worst);
119*77b80299SAndroid Build Coastguard Worker         m_transactions += 1;
120*77b80299SAndroid Build Coastguard Worker         m_total_time += time;
121*77b80299SAndroid Build Coastguard Worker     }
122*77b80299SAndroid Build Coastguard Worker     // Combine two sets of latency data points and update the aggregation info.
combineProcResults123*77b80299SAndroid Build Coastguard Worker     static ProcResults combine(const ProcResults& a, const ProcResults& b) {
124*77b80299SAndroid Build Coastguard Worker         ProcResults ret;
125*77b80299SAndroid Build Coastguard Worker         for (uint32_t i = 0; i < num_buckets; i++) {
126*77b80299SAndroid Build Coastguard Worker             ret.m_buckets[i] = a.m_buckets[i] + b.m_buckets[i];
127*77b80299SAndroid Build Coastguard Worker         }
128*77b80299SAndroid Build Coastguard Worker         ret.m_worst = max(a.m_worst, b.m_worst);
129*77b80299SAndroid Build Coastguard Worker         ret.m_best = min(a.m_best, b.m_best);
130*77b80299SAndroid Build Coastguard Worker         ret.m_transactions = a.m_transactions + b.m_transactions;
131*77b80299SAndroid Build Coastguard Worker         ret.m_total_time = a.m_total_time + b.m_total_time;
132*77b80299SAndroid Build Coastguard Worker         return ret;
133*77b80299SAndroid Build Coastguard Worker     }
134*77b80299SAndroid Build Coastguard Worker     // Calculate and report the final aggregated results.
dumpProcResults135*77b80299SAndroid Build Coastguard Worker     void dump() {
136*77b80299SAndroid Build Coastguard Worker         double best = (double) m_best / 1.0E6;
137*77b80299SAndroid Build Coastguard Worker         double worst = (double) m_worst / 1.0E6;
138*77b80299SAndroid Build Coastguard Worker         double average = (double) m_total_time / m_transactions / 1.0E6;
139*77b80299SAndroid Build Coastguard Worker         cout << "average:"
140*77b80299SAndroid Build Coastguard Worker              << average
141*77b80299SAndroid Build Coastguard Worker              << "ms worst:"
142*77b80299SAndroid Build Coastguard Worker              << worst
143*77b80299SAndroid Build Coastguard Worker              << "ms best:"
144*77b80299SAndroid Build Coastguard Worker              << best
145*77b80299SAndroid Build Coastguard Worker              << "ms"
146*77b80299SAndroid Build Coastguard Worker              << endl;
147*77b80299SAndroid Build Coastguard Worker 
148*77b80299SAndroid Build Coastguard Worker         uint64_t cur_total = 0;
149*77b80299SAndroid Build Coastguard Worker         for (uint32_t i = 0; i < num_buckets; i++) {
150*77b80299SAndroid Build Coastguard Worker             float cur_time = time_per_bucket_ms * i + 0.5f * time_per_bucket_ms;
151*77b80299SAndroid Build Coastguard Worker             if ((cur_total < 0.5f * m_transactions)
152*77b80299SAndroid Build Coastguard Worker                 && (cur_total + m_buckets[i] >= 0.5f * m_transactions)) {
153*77b80299SAndroid Build Coastguard Worker                 cout << "50%: " << cur_time << " ";
154*77b80299SAndroid Build Coastguard Worker             }
155*77b80299SAndroid Build Coastguard Worker             if ((cur_total < 0.9f * m_transactions)
156*77b80299SAndroid Build Coastguard Worker                 && (cur_total + m_buckets[i] >= 0.9f * m_transactions)) {
157*77b80299SAndroid Build Coastguard Worker                 cout << "90%: " << cur_time << " ";
158*77b80299SAndroid Build Coastguard Worker             }
159*77b80299SAndroid Build Coastguard Worker             if ((cur_total < 0.95f * m_transactions)
160*77b80299SAndroid Build Coastguard Worker                 && (cur_total + m_buckets[i] >= 0.95f * m_transactions)) {
161*77b80299SAndroid Build Coastguard Worker                 cout << "95%: " << cur_time << " ";
162*77b80299SAndroid Build Coastguard Worker             }
163*77b80299SAndroid Build Coastguard Worker             if ((cur_total < 0.99f * m_transactions)
164*77b80299SAndroid Build Coastguard Worker                 && (cur_total + m_buckets[i] >= 0.99f * m_transactions)) {
165*77b80299SAndroid Build Coastguard Worker                 cout << "99%: " << cur_time << " ";
166*77b80299SAndroid Build Coastguard Worker             }
167*77b80299SAndroid Build Coastguard Worker             cur_total += m_buckets[i];
168*77b80299SAndroid Build Coastguard Worker         }
169*77b80299SAndroid Build Coastguard Worker         cout << endl;
170*77b80299SAndroid Build Coastguard Worker 
171*77b80299SAndroid Build Coastguard Worker     }
172*77b80299SAndroid Build Coastguard Worker };
173*77b80299SAndroid Build Coastguard Worker 
generateServiceName(int num)174*77b80299SAndroid Build Coastguard Worker string generateServiceName(int num) {
175*77b80299SAndroid Build Coastguard Worker     string serviceName = "hwbinderService" + to_string(num);
176*77b80299SAndroid Build Coastguard Worker     return serviceName;
177*77b80299SAndroid Build Coastguard Worker }
178*77b80299SAndroid Build Coastguard Worker 
service_fx(const string & serviceName,Pipe p)179*77b80299SAndroid Build Coastguard Worker void service_fx(const string &serviceName, Pipe p) {
180*77b80299SAndroid Build Coastguard Worker     // Start service.
181*77b80299SAndroid Build Coastguard Worker     sp<IBenchmark> server = IBenchmark::getService(serviceName, true);
182*77b80299SAndroid Build Coastguard Worker     ALOGD("Registering %s", serviceName.c_str());
183*77b80299SAndroid Build Coastguard Worker     status_t status = server->registerAsService(serviceName);
184*77b80299SAndroid Build Coastguard Worker     if (status != ::android::OK) {
185*77b80299SAndroid Build Coastguard Worker         ALOGE("Failed to register service %s", serviceName.c_str());
186*77b80299SAndroid Build Coastguard Worker         exit(EXIT_FAILURE);
187*77b80299SAndroid Build Coastguard Worker     }
188*77b80299SAndroid Build Coastguard Worker 
189*77b80299SAndroid Build Coastguard Worker     ALOGD("Starting %s", serviceName.c_str());
190*77b80299SAndroid Build Coastguard Worker 
191*77b80299SAndroid Build Coastguard Worker     // Signal service started to master and wait to exit.
192*77b80299SAndroid Build Coastguard Worker     p.signal();
193*77b80299SAndroid Build Coastguard Worker     p.wait();
194*77b80299SAndroid Build Coastguard Worker     exit(EXIT_SUCCESS);
195*77b80299SAndroid Build Coastguard Worker }
196*77b80299SAndroid Build Coastguard Worker 
worker_fx(int num,int iterations,int service_count,bool get_stub,Pipe p)197*77b80299SAndroid Build Coastguard Worker void worker_fx(
198*77b80299SAndroid Build Coastguard Worker         int num,
199*77b80299SAndroid Build Coastguard Worker         int iterations,
200*77b80299SAndroid Build Coastguard Worker         int service_count,
201*77b80299SAndroid Build Coastguard Worker         bool get_stub,
202*77b80299SAndroid Build Coastguard Worker         Pipe p) {
203*77b80299SAndroid Build Coastguard Worker     srand(num);
204*77b80299SAndroid Build Coastguard Worker     p.signal();
205*77b80299SAndroid Build Coastguard Worker     p.wait();
206*77b80299SAndroid Build Coastguard Worker 
207*77b80299SAndroid Build Coastguard Worker     // Get references to test services.
208*77b80299SAndroid Build Coastguard Worker     vector<sp<IBenchmark>> workers;
209*77b80299SAndroid Build Coastguard Worker 
210*77b80299SAndroid Build Coastguard Worker     for (int i = 0; i < service_count; i++) {
211*77b80299SAndroid Build Coastguard Worker         sp<IBenchmark> service = IBenchmark::getService(
212*77b80299SAndroid Build Coastguard Worker                 generateServiceName(i), get_stub);
213*77b80299SAndroid Build Coastguard Worker         ASSERT_TRUE(service != NULL);
214*77b80299SAndroid Build Coastguard Worker         if (get_stub) {
215*77b80299SAndroid Build Coastguard Worker             ASSERT_TRUE(!service->isRemote());
216*77b80299SAndroid Build Coastguard Worker         } else {
217*77b80299SAndroid Build Coastguard Worker             ASSERT_TRUE(service->isRemote());
218*77b80299SAndroid Build Coastguard Worker         }
219*77b80299SAndroid Build Coastguard Worker         workers.push_back(service);
220*77b80299SAndroid Build Coastguard Worker     }
221*77b80299SAndroid Build Coastguard Worker 
222*77b80299SAndroid Build Coastguard Worker     ProcResults results;
223*77b80299SAndroid Build Coastguard Worker     chrono::time_point<chrono::high_resolution_clock> start, end;
224*77b80299SAndroid Build Coastguard Worker     // Prepare data to IPC
225*77b80299SAndroid Build Coastguard Worker     hidl_vec<uint8_t> data_vec;
226*77b80299SAndroid Build Coastguard Worker     data_vec.resize(16);
227*77b80299SAndroid Build Coastguard Worker     for (size_t i = 0; i < data_vec.size(); i++) {
228*77b80299SAndroid Build Coastguard Worker         data_vec[i] = i;
229*77b80299SAndroid Build Coastguard Worker     }
230*77b80299SAndroid Build Coastguard Worker     // Run the benchmark.
231*77b80299SAndroid Build Coastguard Worker     for (int i = 0; i < iterations; i++) {
232*77b80299SAndroid Build Coastguard Worker         // Randomly pick a service.
233*77b80299SAndroid Build Coastguard Worker         int target = rand() % service_count;
234*77b80299SAndroid Build Coastguard Worker 
235*77b80299SAndroid Build Coastguard Worker         start = chrono::high_resolution_clock::now();
236*77b80299SAndroid Build Coastguard Worker         Return<void> ret = workers[target]->sendVec(data_vec, [&](const auto &) {});
237*77b80299SAndroid Build Coastguard Worker         if (!ret.isOk()) {
238*77b80299SAndroid Build Coastguard Worker             cout << "thread " << num << " failed status: "
239*77b80299SAndroid Build Coastguard Worker                 << ret.description() << endl;
240*77b80299SAndroid Build Coastguard Worker             exit(EXIT_FAILURE);
241*77b80299SAndroid Build Coastguard Worker         }
242*77b80299SAndroid Build Coastguard Worker         end = chrono::high_resolution_clock::now();
243*77b80299SAndroid Build Coastguard Worker 
244*77b80299SAndroid Build Coastguard Worker         uint64_t cur_time = uint64_t(
245*77b80299SAndroid Build Coastguard Worker                chrono::duration_cast<chrono::nanoseconds>(end - start).count());
246*77b80299SAndroid Build Coastguard Worker         results.add_time(cur_time);
247*77b80299SAndroid Build Coastguard Worker     }
248*77b80299SAndroid Build Coastguard Worker     // Signal completion to master and wait.
249*77b80299SAndroid Build Coastguard Worker     p.signal();
250*77b80299SAndroid Build Coastguard Worker     p.wait();
251*77b80299SAndroid Build Coastguard Worker 
252*77b80299SAndroid Build Coastguard Worker     // Send results to master and wait for go to exit.
253*77b80299SAndroid Build Coastguard Worker     p.send(results);
254*77b80299SAndroid Build Coastguard Worker     p.wait();
255*77b80299SAndroid Build Coastguard Worker 
256*77b80299SAndroid Build Coastguard Worker     exit (EXIT_SUCCESS);
257*77b80299SAndroid Build Coastguard Worker }
258*77b80299SAndroid Build Coastguard Worker 
make_service(string service_name)259*77b80299SAndroid Build Coastguard Worker Pipe make_service(string service_name) {
260*77b80299SAndroid Build Coastguard Worker     auto pipe_pair = Pipe::createPipePair();
261*77b80299SAndroid Build Coastguard Worker     pid_t pid = fork();
262*77b80299SAndroid Build Coastguard Worker     if (pid) {
263*77b80299SAndroid Build Coastguard Worker         /* parent */
264*77b80299SAndroid Build Coastguard Worker         return std::move(get<0>(pipe_pair));
265*77b80299SAndroid Build Coastguard Worker     } else {
266*77b80299SAndroid Build Coastguard Worker         /* child */
267*77b80299SAndroid Build Coastguard Worker         service_fx(service_name, std::move(get<1>(pipe_pair)));
268*77b80299SAndroid Build Coastguard Worker         /* never get here */
269*77b80299SAndroid Build Coastguard Worker         return std::move(get<0>(pipe_pair));
270*77b80299SAndroid Build Coastguard Worker     }
271*77b80299SAndroid Build Coastguard Worker }
272*77b80299SAndroid Build Coastguard Worker 
make_worker(int num,int iterations,int service_count,bool get_stub)273*77b80299SAndroid Build Coastguard Worker Pipe make_worker(int num, int iterations, int service_count, bool get_stub) {
274*77b80299SAndroid Build Coastguard Worker     auto pipe_pair = Pipe::createPipePair();
275*77b80299SAndroid Build Coastguard Worker     pid_t pid = fork();
276*77b80299SAndroid Build Coastguard Worker     if (pid) {
277*77b80299SAndroid Build Coastguard Worker         /* parent */
278*77b80299SAndroid Build Coastguard Worker         return std::move(get<0>(pipe_pair));
279*77b80299SAndroid Build Coastguard Worker     } else {
280*77b80299SAndroid Build Coastguard Worker         /* child */
281*77b80299SAndroid Build Coastguard Worker         worker_fx(num, iterations, service_count, get_stub,
282*77b80299SAndroid Build Coastguard Worker                   std::move(get<1>(pipe_pair)));
283*77b80299SAndroid Build Coastguard Worker         /* never get here */
284*77b80299SAndroid Build Coastguard Worker         return std::move(get<0>(pipe_pair));
285*77b80299SAndroid Build Coastguard Worker     }
286*77b80299SAndroid Build Coastguard Worker }
287*77b80299SAndroid Build Coastguard Worker 
wait_all(vector<Pipe> & v)288*77b80299SAndroid Build Coastguard Worker void wait_all(vector<Pipe>& v) {
289*77b80299SAndroid Build Coastguard Worker     for (size_t i = 0; i < v.size(); i++) {
290*77b80299SAndroid Build Coastguard Worker         v[i].wait();
291*77b80299SAndroid Build Coastguard Worker     }
292*77b80299SAndroid Build Coastguard Worker }
293*77b80299SAndroid Build Coastguard Worker 
signal_all(vector<Pipe> & v)294*77b80299SAndroid Build Coastguard Worker void signal_all(vector<Pipe>& v) {
295*77b80299SAndroid Build Coastguard Worker     for (size_t i = 0; i < v.size(); i++) {
296*77b80299SAndroid Build Coastguard Worker         v[i].signal();
297*77b80299SAndroid Build Coastguard Worker     }
298*77b80299SAndroid Build Coastguard Worker }
299*77b80299SAndroid Build Coastguard Worker 
main(int argc,char * argv[])300*77b80299SAndroid Build Coastguard Worker int main(int argc, char *argv[]) {
301*77b80299SAndroid Build Coastguard Worker     android::hardware::details::setTrebleTestingOverride(true);
302*77b80299SAndroid Build Coastguard Worker 
303*77b80299SAndroid Build Coastguard Worker     enum HwBinderMode {
304*77b80299SAndroid Build Coastguard Worker         kBinderize = 0,
305*77b80299SAndroid Build Coastguard Worker         kPassthrough = 1,
306*77b80299SAndroid Build Coastguard Worker     };
307*77b80299SAndroid Build Coastguard Worker     HwBinderMode mode = HwBinderMode::kBinderize;
308*77b80299SAndroid Build Coastguard Worker 
309*77b80299SAndroid Build Coastguard Worker     // Num of workers.
310*77b80299SAndroid Build Coastguard Worker     int workers = 2;
311*77b80299SAndroid Build Coastguard Worker     // Num of services.
312*77b80299SAndroid Build Coastguard Worker     int services = -1;
313*77b80299SAndroid Build Coastguard Worker     int iterations = 10000;
314*77b80299SAndroid Build Coastguard Worker 
315*77b80299SAndroid Build Coastguard Worker     vector<Pipe> worker_pipes;
316*77b80299SAndroid Build Coastguard Worker     vector<Pipe> service_pipes;
317*77b80299SAndroid Build Coastguard Worker 
318*77b80299SAndroid Build Coastguard Worker     // Parse arguments.
319*77b80299SAndroid Build Coastguard Worker     for (int i = 1; i < argc; i++) {
320*77b80299SAndroid Build Coastguard Worker         if (string(argv[i]) == "-m") {
321*77b80299SAndroid Build Coastguard Worker             if (!strcmp(argv[i + 1], "PASSTHROUGH")) {
322*77b80299SAndroid Build Coastguard Worker                 mode = HwBinderMode::kPassthrough;
323*77b80299SAndroid Build Coastguard Worker             }
324*77b80299SAndroid Build Coastguard Worker             i++;
325*77b80299SAndroid Build Coastguard Worker             continue;
326*77b80299SAndroid Build Coastguard Worker         }
327*77b80299SAndroid Build Coastguard Worker         if (string(argv[i]) == "-w") {
328*77b80299SAndroid Build Coastguard Worker             workers = atoi(argv[i + 1]);
329*77b80299SAndroid Build Coastguard Worker             i++;
330*77b80299SAndroid Build Coastguard Worker             continue;
331*77b80299SAndroid Build Coastguard Worker         }
332*77b80299SAndroid Build Coastguard Worker         if (string(argv[i]) == "-i") {
333*77b80299SAndroid Build Coastguard Worker             iterations = atoi(argv[i + 1]);
334*77b80299SAndroid Build Coastguard Worker             i++;
335*77b80299SAndroid Build Coastguard Worker             continue;
336*77b80299SAndroid Build Coastguard Worker         }
337*77b80299SAndroid Build Coastguard Worker         if (string(argv[i]) == "-s") {
338*77b80299SAndroid Build Coastguard Worker             services = atoi(argv[i + 1]);
339*77b80299SAndroid Build Coastguard Worker             i++;
340*77b80299SAndroid Build Coastguard Worker             continue;
341*77b80299SAndroid Build Coastguard Worker         }
342*77b80299SAndroid Build Coastguard Worker     }
343*77b80299SAndroid Build Coastguard Worker     // If service number is not provided, set it the same as the worker number.
344*77b80299SAndroid Build Coastguard Worker     if (services == -1) {
345*77b80299SAndroid Build Coastguard Worker         services = workers;
346*77b80299SAndroid Build Coastguard Worker     }
347*77b80299SAndroid Build Coastguard Worker     if (mode == HwBinderMode::kBinderize) {
348*77b80299SAndroid Build Coastguard Worker         // Create services.
349*77b80299SAndroid Build Coastguard Worker         vector<pid_t> pIds;
350*77b80299SAndroid Build Coastguard Worker         for (int i = 0; i < services; i++) {
351*77b80299SAndroid Build Coastguard Worker             string serviceName = generateServiceName(i);
352*77b80299SAndroid Build Coastguard Worker             cout << "creating service: " << serviceName << endl;
353*77b80299SAndroid Build Coastguard Worker             service_pipes.push_back(make_service(serviceName));
354*77b80299SAndroid Build Coastguard Worker         }
355*77b80299SAndroid Build Coastguard Worker         // Wait until all services are up.
356*77b80299SAndroid Build Coastguard Worker         wait_all(service_pipes);
357*77b80299SAndroid Build Coastguard Worker     }
358*77b80299SAndroid Build Coastguard Worker 
359*77b80299SAndroid Build Coastguard Worker     // Create workers (test clients).
360*77b80299SAndroid Build Coastguard Worker     bool get_stub = mode == HwBinderMode::kBinderize ? false : true;
361*77b80299SAndroid Build Coastguard Worker     for (int i = 0; i < workers; i++) {
362*77b80299SAndroid Build Coastguard Worker         worker_pipes.push_back(make_worker(i, iterations, services, get_stub));
363*77b80299SAndroid Build Coastguard Worker     }
364*77b80299SAndroid Build Coastguard Worker     // Wait untill all workers are ready.
365*77b80299SAndroid Build Coastguard Worker     wait_all(worker_pipes);
366*77b80299SAndroid Build Coastguard Worker 
367*77b80299SAndroid Build Coastguard Worker     // Run the workers and wait for completion.
368*77b80299SAndroid Build Coastguard Worker     chrono::time_point<chrono::high_resolution_clock> start, end;
369*77b80299SAndroid Build Coastguard Worker     cout << "waiting for workers to complete" << endl;
370*77b80299SAndroid Build Coastguard Worker     start = chrono::high_resolution_clock::now();
371*77b80299SAndroid Build Coastguard Worker     signal_all(worker_pipes);
372*77b80299SAndroid Build Coastguard Worker     wait_all(worker_pipes);
373*77b80299SAndroid Build Coastguard Worker     end = chrono::high_resolution_clock::now();
374*77b80299SAndroid Build Coastguard Worker 
375*77b80299SAndroid Build Coastguard Worker     // Calculate overall throughput.
376*77b80299SAndroid Build Coastguard Worker     double iterations_per_sec = double(iterations * workers)
377*77b80299SAndroid Build Coastguard Worker         / (chrono::duration_cast < chrono::nanoseconds
378*77b80299SAndroid Build Coastguard Worker             > (end - start).count() / 1.0E9);
379*77b80299SAndroid Build Coastguard Worker     cout << "iterations per sec: " << iterations_per_sec << endl;
380*77b80299SAndroid Build Coastguard Worker 
381*77b80299SAndroid Build Coastguard Worker     // Collect all results from the workers.
382*77b80299SAndroid Build Coastguard Worker     cout << "collecting results" << endl;
383*77b80299SAndroid Build Coastguard Worker     signal_all(worker_pipes);
384*77b80299SAndroid Build Coastguard Worker     ProcResults tot_results;
385*77b80299SAndroid Build Coastguard Worker     for (int i = 0; i < workers; i++) {
386*77b80299SAndroid Build Coastguard Worker         ProcResults tmp_results;
387*77b80299SAndroid Build Coastguard Worker         worker_pipes[i].recv(tmp_results);
388*77b80299SAndroid Build Coastguard Worker         tot_results = ProcResults::combine(tot_results, tmp_results);
389*77b80299SAndroid Build Coastguard Worker     }
390*77b80299SAndroid Build Coastguard Worker     tot_results.dump();
391*77b80299SAndroid Build Coastguard Worker 
392*77b80299SAndroid Build Coastguard Worker     if (mode == HwBinderMode::kBinderize) {
393*77b80299SAndroid Build Coastguard Worker         // Kill all the services.
394*77b80299SAndroid Build Coastguard Worker         cout << "killing services" << endl;
395*77b80299SAndroid Build Coastguard Worker         signal_all(service_pipes);
396*77b80299SAndroid Build Coastguard Worker         for (int i = 0; i < services; i++) {
397*77b80299SAndroid Build Coastguard Worker             int status;
398*77b80299SAndroid Build Coastguard Worker             wait(&status);
399*77b80299SAndroid Build Coastguard Worker             if (status != 0) {
400*77b80299SAndroid Build Coastguard Worker                 cout << "nonzero child status" << status << endl;
401*77b80299SAndroid Build Coastguard Worker             }
402*77b80299SAndroid Build Coastguard Worker         }
403*77b80299SAndroid Build Coastguard Worker     }
404*77b80299SAndroid Build Coastguard Worker     // Kill all the workers.
405*77b80299SAndroid Build Coastguard Worker     cout << "killing workers" << endl;
406*77b80299SAndroid Build Coastguard Worker     signal_all(worker_pipes);
407*77b80299SAndroid Build Coastguard Worker     for (int i = 0; i < workers; i++) {
408*77b80299SAndroid Build Coastguard Worker         int status;
409*77b80299SAndroid Build Coastguard Worker         wait(&status);
410*77b80299SAndroid Build Coastguard Worker         if (status != 0) {
411*77b80299SAndroid Build Coastguard Worker             cout << "nonzero child status" << status << endl;
412*77b80299SAndroid Build Coastguard Worker         }
413*77b80299SAndroid Build Coastguard Worker     }
414*77b80299SAndroid Build Coastguard Worker     return 0;
415*77b80299SAndroid Build Coastguard Worker }
416