blob: 865f0ec9a4c51a02f405544285d81ae2de42b8af [file] [log] [blame]
Steven Morelandcda60852021-04-14 23:45:32 +00001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <BnBinderRpcBenchmark.h>
18#include <android-base/logging.h>
19#include <benchmark/benchmark.h>
20#include <binder/Binder.h>
Steven Moreland1ebdc702021-07-28 18:46:15 -070021#include <binder/IPCThreadState.h>
22#include <binder/IServiceManager.h>
23#include <binder/ProcessState.h>
Yifan Hongaecdd172021-09-21 14:53:13 -070024#include <binder/RpcCertificateFormat.h>
25#include <binder/RpcCertificateVerifier.h>
Steven Morelandcda60852021-04-14 23:45:32 +000026#include <binder/RpcServer.h>
Steven Morelandbdb53ab2021-05-05 17:57:41 +000027#include <binder/RpcSession.h>
Yifan Honge0e53282021-09-23 18:37:21 -070028#include <binder/RpcTlsTestUtils.h>
Yifan Hongaecdd172021-09-21 14:53:13 -070029#include <binder/RpcTlsUtils.h>
30#include <binder/RpcTransportRaw.h>
31#include <binder/RpcTransportTls.h>
32#include <openssl/ssl.h>
Steven Morelandcda60852021-04-14 23:45:32 +000033
34#include <thread>
35
Steven Moreland656e9d12021-07-29 17:33:53 -070036#include <signal.h>
Steven Moreland1ebdc702021-07-28 18:46:15 -070037#include <sys/prctl.h>
Steven Morelandcda60852021-04-14 23:45:32 +000038#include <sys/types.h>
39#include <unistd.h>
40
41using android::BBinder;
Steven Moreland1ebdc702021-07-28 18:46:15 -070042using android::defaultServiceManager;
Steven Morelandcda60852021-04-14 23:45:32 +000043using android::IBinder;
44using android::interface_cast;
Steven Moreland1ebdc702021-07-28 18:46:15 -070045using android::IPCThreadState;
46using android::IServiceManager;
Steven Morelandcda60852021-04-14 23:45:32 +000047using android::OK;
Steven Moreland1ebdc702021-07-28 18:46:15 -070048using android::ProcessState;
Yifan Hongaecdd172021-09-21 14:53:13 -070049using android::RpcAuthPreSigned;
50using android::RpcCertificateFormat;
51using android::RpcCertificateVerifier;
Yifan Hong9809add2021-09-23 19:06:58 -070052using android::RpcCertificateVerifierNoOp;
Steven Morelandcda60852021-04-14 23:45:32 +000053using android::RpcServer;
Steven Morelandbdb53ab2021-05-05 17:57:41 +000054using android::RpcSession;
Yifan Hongaecdd172021-09-21 14:53:13 -070055using android::RpcTransportCtxFactory;
56using android::RpcTransportCtxFactoryRaw;
57using android::RpcTransportCtxFactoryTls;
Steven Morelandcda60852021-04-14 23:45:32 +000058using android::sp;
Steven Moreland2372f9d2021-08-05 15:42:01 -070059using android::status_t;
60using android::statusToString;
Steven Moreland1ebdc702021-07-28 18:46:15 -070061using android::String16;
Steven Morelandcda60852021-04-14 23:45:32 +000062using android::binder::Status;
63
64class MyBinderRpcBenchmark : public BnBinderRpcBenchmark {
65 Status repeatString(const std::string& str, std::string* out) override {
66 *out = str;
67 return Status::ok();
68 }
Steven Morelandce240ce2021-08-05 13:02:37 -070069 Status repeatBinder(const sp<IBinder>& binder, sp<IBinder>* out) override {
70 *out = binder;
71 return Status::ok();
72 }
73 Status repeatBytes(const std::vector<uint8_t>& bytes, std::vector<uint8_t>* out) override {
74 *out = bytes;
Steven Morelandcda60852021-04-14 23:45:32 +000075 return Status::ok();
76 }
Steven Morelandb85e7f72023-09-13 21:02:50 +000077
78 class CountedBinder : public BBinder {
79 public:
80 CountedBinder(const sp<MyBinderRpcBenchmark>& parent) : mParent(parent) {
81 std::lock_guard<std::mutex> l(mParent->mCountMutex);
82 mParent->mBinderCount++;
83 // std::cout << "Count + is now " << mParent->mBinderCount << std::endl;
84 }
85 ~CountedBinder() {
86 {
87 std::lock_guard<std::mutex> l(mParent->mCountMutex);
88 mParent->mBinderCount--;
89 // std::cout << "Count - is now " << mParent->mBinderCount << std::endl;
90
91 // skip notify
92 if (mParent->mBinderCount != 0) return;
93 }
94 mParent->mCountCv.notify_one();
95 }
96
97 private:
98 sp<MyBinderRpcBenchmark> mParent;
99 };
100
101 Status gimmeBinder(sp<IBinder>* out) override {
102 *out = sp<CountedBinder>::make(sp<MyBinderRpcBenchmark>::fromExisting(this));
103 return Status::ok();
104 }
105 Status waitGimmesDestroyed() override {
106 std::unique_lock<std::mutex> l(mCountMutex);
107 mCountCv.wait(l, [&] { return mBinderCount == 0; });
108 return Status::ok();
109 }
110
111 friend class CountedBinder;
112 std::mutex mCountMutex;
113 std::condition_variable mCountCv;
114 size_t mBinderCount;
Steven Morelandcda60852021-04-14 23:45:32 +0000115};
116
Steven Moreland1ebdc702021-07-28 18:46:15 -0700117enum Transport {
118 KERNEL,
119 RPC,
Yifan Hongaecdd172021-09-21 14:53:13 -0700120 RPC_TLS,
Steven Moreland1ebdc702021-07-28 18:46:15 -0700121};
Steven Morelandcda60852021-04-14 23:45:32 +0000122
Steven Morelandce240ce2021-08-05 13:02:37 -0700123static const std::initializer_list<int64_t> kTransportList = {
Steven Moreland1ebdc702021-07-28 18:46:15 -0700124#ifdef __BIONIC__
Steven Morelandce240ce2021-08-05 13:02:37 -0700125 Transport::KERNEL,
Steven Moreland1ebdc702021-07-28 18:46:15 -0700126#endif
Yifan Hongaecdd172021-09-21 14:53:13 -0700127 Transport::RPC,
128 Transport::RPC_TLS,
129};
130
Yifan Hongaecdd172021-09-21 14:53:13 -0700131std::unique_ptr<RpcTransportCtxFactory> makeFactoryTls() {
132 auto pkey = android::makeKeyPairForSelfSignedCert();
133 CHECK_NE(pkey.get(), nullptr);
134 auto cert = android::makeSelfSignedCert(pkey.get(), android::kCertValidSeconds);
135 CHECK_NE(cert.get(), nullptr);
136
Yifan Hongdc767652021-09-23 19:38:38 -0700137 auto verifier = std::make_shared<RpcCertificateVerifierNoOp>(OK);
Yifan Hongaecdd172021-09-21 14:53:13 -0700138 auto auth = std::make_unique<RpcAuthPreSigned>(std::move(pkey), std::move(cert));
139 return RpcTransportCtxFactoryTls::make(verifier, std::move(auth));
140}
Steven Moreland1ebdc702021-07-28 18:46:15 -0700141
142static sp<RpcSession> gSession = RpcSession::make();
Steven Moreland67f85902023-03-15 01:13:49 +0000143static sp<IBinder> gRpcBinder;
Yifan Hong9809add2021-09-23 19:06:58 -0700144// Certificate validation happens during handshake and does not affect the result of benchmarks.
145// Skip certificate validation to simplify the setup process.
Yifan Hongaecdd172021-09-21 14:53:13 -0700146static sp<RpcSession> gSessionTls = RpcSession::make(makeFactoryTls());
Steven Moreland67f85902023-03-15 01:13:49 +0000147static sp<IBinder> gRpcTlsBinder;
Steven Moreland1ebdc702021-07-28 18:46:15 -0700148#ifdef __BIONIC__
149static const String16 kKernelBinderInstance = String16(u"binderRpcBenchmark-control");
150static sp<IBinder> gKernelBinder;
151#endif
152
153static sp<IBinder> getBinderForOptions(benchmark::State& state) {
154 Transport transport = static_cast<Transport>(state.range(0));
155 switch (transport) {
156#ifdef __BIONIC__
157 case KERNEL:
158 return gKernelBinder;
159#endif
160 case RPC:
Steven Moreland67f85902023-03-15 01:13:49 +0000161 return gRpcBinder;
Yifan Hongaecdd172021-09-21 14:53:13 -0700162 case RPC_TLS:
Steven Moreland67f85902023-03-15 01:13:49 +0000163 return gRpcTlsBinder;
Steven Moreland1ebdc702021-07-28 18:46:15 -0700164 default:
165 LOG(FATAL) << "Unknown transport value: " << transport;
166 return nullptr;
Steven Morelandcda60852021-04-14 23:45:32 +0000167 }
168}
Steven Morelandcda60852021-04-14 23:45:32 +0000169
Steven Moreland90b82892023-05-11 00:10:26 +0000170static void SetLabel(benchmark::State& state) {
171 Transport transport = static_cast<Transport>(state.range(0));
172 switch (transport) {
173#ifdef __BIONIC__
174 case KERNEL:
175 state.SetLabel("kernel");
176 break;
177#endif
178 case RPC:
179 state.SetLabel("rpc");
180 break;
181 case RPC_TLS:
182 state.SetLabel("rpc_tls");
183 break;
184 default:
185 LOG(FATAL) << "Unknown transport value: " << transport;
186 }
187}
188
Steven Morelandcda60852021-04-14 23:45:32 +0000189void BM_pingTransaction(benchmark::State& state) {
Steven Moreland1ebdc702021-07-28 18:46:15 -0700190 sp<IBinder> binder = getBinderForOptions(state);
Steven Morelandcda60852021-04-14 23:45:32 +0000191
192 while (state.KeepRunning()) {
193 CHECK_EQ(OK, binder->pingBinder());
194 }
Steven Moreland90b82892023-05-11 00:10:26 +0000195
196 SetLabel(state);
Steven Morelandcda60852021-04-14 23:45:32 +0000197}
Steven Morelandce240ce2021-08-05 13:02:37 -0700198BENCHMARK(BM_pingTransaction)->ArgsProduct({kTransportList});
Steven Morelandcda60852021-04-14 23:45:32 +0000199
Steven Morelandce240ce2021-08-05 13:02:37 -0700200void BM_repeatTwoPageString(benchmark::State& state) {
Steven Moreland1ebdc702021-07-28 18:46:15 -0700201 sp<IBinder> binder = getBinderForOptions(state);
202
Steven Morelandcda60852021-04-14 23:45:32 +0000203 sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
204 CHECK(iface != nullptr);
205
206 // Googlers might see go/another-look-at-aidl-hidl-perf
207 //
208 // When I checked in July 2019, 99.5% of AIDL transactions and 99.99% of HIDL
209 // transactions were less than one page in size (system wide during a test
210 // involving media and camera). This is why this diverges from
211 // binderThroughputTest and hwbinderThroughputTest. Future consideration - get
212 // this data on continuous integration. Here we are testing sending a
213 // transaction of twice this size. In other cases, we should focus on
214 // benchmarks of particular usecases. If individual binder transactions like
215 // the ones tested here are fast, then Android performance will be dominated
216 // by how many binder calls work together (and by factors like the scheduler,
217 // thermal throttling, core choice, etc..).
218 std::string str = std::string(getpagesize() * 2, 'a');
Tomasz Wasilczyke97f3a82024-04-30 10:37:32 -0700219 CHECK_EQ(static_cast<ssize_t>(str.size()), getpagesize() * 2);
Steven Morelandcda60852021-04-14 23:45:32 +0000220
221 while (state.KeepRunning()) {
222 std::string out;
223 Status ret = iface->repeatString(str, &out);
224 CHECK(ret.isOk()) << ret;
225 }
Steven Moreland90b82892023-05-11 00:10:26 +0000226
227 SetLabel(state);
Steven Morelandcda60852021-04-14 23:45:32 +0000228}
Steven Morelandce240ce2021-08-05 13:02:37 -0700229BENCHMARK(BM_repeatTwoPageString)->ArgsProduct({kTransportList});
230
231void BM_throughputForTransportAndBytes(benchmark::State& state) {
232 sp<IBinder> binder = getBinderForOptions(state);
233 sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
234 CHECK(iface != nullptr);
235
236 std::vector<uint8_t> bytes = std::vector<uint8_t>(state.range(1));
237 for (size_t i = 0; i < bytes.size(); i++) {
238 bytes[i] = i % 256;
239 }
240
241 while (state.KeepRunning()) {
242 std::vector<uint8_t> out;
243 Status ret = iface->repeatBytes(bytes, &out);
244 CHECK(ret.isOk()) << ret;
245 }
Steven Moreland90b82892023-05-11 00:10:26 +0000246
247 SetLabel(state);
Steven Morelandce240ce2021-08-05 13:02:37 -0700248}
249BENCHMARK(BM_throughputForTransportAndBytes)
250 ->ArgsProduct({kTransportList,
251 {64, 1024, 2048, 4096, 8182, 16364, 32728, 65535, 65536, 65537}});
Steven Morelandcda60852021-04-14 23:45:32 +0000252
Steven Morelandb85e7f72023-09-13 21:02:50 +0000253void BM_collectProxies(benchmark::State& state) {
254 sp<IBinder> binder = getBinderForOptions(state);
255 sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
256 CHECK(iface != nullptr);
257
258 const size_t kNumIters = state.range(1);
259
260 while (state.KeepRunning()) {
261 std::vector<sp<IBinder>> out;
262 out.resize(kNumIters);
263
264 for (size_t i = 0; i < kNumIters; i++) {
265 Status ret = iface->gimmeBinder(&out[i]);
266 CHECK(ret.isOk()) << ret;
267 }
268
269 out.clear();
270
271 // we are using a thread up to wait, so make a call to
272 // force all refcounts to be updated first - current
273 // binder behavior means we really don't need to wait,
274 // so code which is waiting is really there to protect
275 // against any future changes that could delay destruction
276 android::IInterface::asBinder(iface)->pingBinder();
277
278 iface->waitGimmesDestroyed();
279 }
280
281 SetLabel(state);
282}
283BENCHMARK(BM_collectProxies)->ArgsProduct({kTransportList, {10, 100, 1000, 5000, 10000, 20000}});
284
Steven Morelandcda60852021-04-14 23:45:32 +0000285void BM_repeatBinder(benchmark::State& state) {
Steven Morelandb9c49622021-08-10 17:39:10 -0700286 sp<IBinder> binder = getBinderForOptions(state);
Steven Morelandcda60852021-04-14 23:45:32 +0000287 CHECK(binder != nullptr);
288 sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
289 CHECK(iface != nullptr);
290
291 while (state.KeepRunning()) {
292 // force creation of a new address
293 sp<IBinder> binder = sp<BBinder>::make();
294
295 sp<IBinder> out;
296 Status ret = iface->repeatBinder(binder, &out);
297 CHECK(ret.isOk()) << ret;
298 }
Steven Moreland90b82892023-05-11 00:10:26 +0000299
300 SetLabel(state);
Steven Morelandcda60852021-04-14 23:45:32 +0000301}
Steven Morelandce240ce2021-08-05 13:02:37 -0700302BENCHMARK(BM_repeatBinder)->ArgsProduct({kTransportList});
Steven Morelandcda60852021-04-14 23:45:32 +0000303
Yifan Hongaecdd172021-09-21 14:53:13 -0700304void forkRpcServer(const char* addr, const sp<RpcServer>& server) {
305 if (0 == fork()) {
306 prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay
307 server->setRootObject(sp<MyBinderRpcBenchmark>::make());
Yifan Hongaecdd172021-09-21 14:53:13 -0700308 CHECK_EQ(OK, server->setupUnixDomainServer(addr));
309 server->join();
310 exit(1);
311 }
312}
313
314void setupClient(const sp<RpcSession>& session, const char* addr) {
315 status_t status;
316 for (size_t tries = 0; tries < 5; tries++) {
317 usleep(10000);
318 status = session->setupUnixDomainClient(addr);
319 if (status == OK) break;
320 }
321 CHECK_EQ(status, OK) << "Could not connect: " << addr << ": " << statusToString(status).c_str();
322}
323
Steven Morelandcda60852021-04-14 23:45:32 +0000324int main(int argc, char** argv) {
325 ::benchmark::Initialize(&argc, argv);
326 if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
327
Steven Moreland1ebdc702021-07-28 18:46:15 -0700328#ifdef __BIONIC__
329 if (0 == fork()) {
330 prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay
331 CHECK_EQ(OK,
332 defaultServiceManager()->addService(kKernelBinderInstance,
333 sp<MyBinderRpcBenchmark>::make()));
334 IPCThreadState::self()->joinThreadPool();
Steven Moreland656e9d12021-07-29 17:33:53 -0700335 exit(1);
Steven Moreland1ebdc702021-07-28 18:46:15 -0700336 }
337
338 ProcessState::self()->setThreadPoolMaxThreadCount(1);
339 ProcessState::self()->startThreadPool();
340
341 gKernelBinder = defaultServiceManager()->waitForService(kKernelBinderInstance);
342 CHECK_NE(nullptr, gKernelBinder.get());
343#endif
344
Yifan Hongaecdd172021-09-21 14:53:13 -0700345 std::string tmp = getenv("TMPDIR") ?: "/tmp";
346
347 std::string addr = tmp + "/binderRpcBenchmark";
348 (void)unlink(addr.c_str());
349 forkRpcServer(addr.c_str(), RpcServer::make(RpcTransportCtxFactoryRaw::make()));
350 setupClient(gSession, addr.c_str());
Steven Moreland67f85902023-03-15 01:13:49 +0000351 gRpcBinder = gSession->getRootObject();
Yifan Hongaecdd172021-09-21 14:53:13 -0700352
353 std::string tlsAddr = tmp + "/binderRpcTlsBenchmark";
354 (void)unlink(tlsAddr.c_str());
355 forkRpcServer(tlsAddr.c_str(), RpcServer::make(makeFactoryTls()));
356 setupClient(gSessionTls, tlsAddr.c_str());
Steven Moreland67f85902023-03-15 01:13:49 +0000357 gRpcTlsBinder = gSessionTls->getRootObject();
Steven Morelandcda60852021-04-14 23:45:32 +0000358
359 ::benchmark::RunSpecifiedBenchmarks();
Steven Moreland3ae982a2021-05-05 18:16:11 +0000360 return 0;
Steven Morelandcda60852021-04-14 23:45:32 +0000361}