diff options
author | 2021-07-28 18:46:15 -0700 | |
---|---|---|
committer | 2021-07-28 19:06:07 -0700 | |
commit | 1ebdc70d175bcc1320a4b42606aafbd54c08624c (patch) | |
tree | 9f13dfb3239fabeb80d7b6832d2072834f4665ad | |
parent | f05210f787603477c75838df5f35ebfe52f81a82 (diff) |
binderRpcBenchmark: device tests kernel as ctrl
Host still tests RPC binder only since kernel binder is only on Android
(by convention!).
On local cuttlefish:
Tests suffixes:
\0 is KERNEL
\1 is RPC
...
---------------------------------------------------------------
Benchmark Time CPU Iterations
---------------------------------------------------------------
BM_pingTransaction/0 28448 ns 18366 ns 36940
BM_pingTransaction/1 39291 ns 26773 ns 25295
BM_repeatString/0 184458 ns 96268 ns 7263
BM_repeatString/1 206385 ns 116369 ns 5947
BM_repeatBinder/0 50475 ns 43567 ns 15896
BM_repeatBinder/1 50722 ns 44386 ns 15857
So the takeaway is that RPC binder has some overhead for very small
transactions.
Future considerations:
- make the RPC calls across processes instead of across threads
- see how scheduler optimizations affect this
Fixes: 194903439
Test: binderRpcBenchmark
Change-Id: Ib7b680091979d142bca4716d62cc579f90bade0f
-rw-r--r-- | libs/binder/tests/binderRpcBenchmark.cpp | 76 |
1 files changed, 64 insertions, 12 deletions
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp index a457e67735..26a0b90977 100644 --- a/libs/binder/tests/binderRpcBenchmark.cpp +++ b/libs/binder/tests/binderRpcBenchmark.cpp @@ -18,21 +18,30 @@ #include <android-base/logging.h> #include <benchmark/benchmark.h> #include <binder/Binder.h> +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> +#include <binder/ProcessState.h> #include <binder/RpcServer.h> #include <binder/RpcSession.h> #include <thread> +#include <sys/prctl.h> #include <sys/types.h> #include <unistd.h> using android::BBinder; +using android::defaultServiceManager; using android::IBinder; using android::interface_cast; +using android::IPCThreadState; +using android::IServiceManager; using android::OK; +using android::ProcessState; using android::RpcServer; using android::RpcSession; using android::sp; +using android::String16; using android::binder::Status; class MyBinderRpcBenchmark : public BnBinderRpcBenchmark { @@ -46,28 +55,51 @@ class MyBinderRpcBenchmark : public BnBinderRpcBenchmark { } }; -static sp<RpcSession> gSession = RpcSession::make(); +enum Transport { + KERNEL, + RPC, +}; -void BM_getRootObject(benchmark::State& state) { - while (state.KeepRunning()) { - CHECK(gSession->getRootObject() != nullptr); +static void EachTransport(benchmark::internal::Benchmark* b) { +#ifdef __BIONIC__ + b->Args({Transport::KERNEL}); +#endif + b->Args({Transport::RPC}); +} + +static sp<RpcSession> gSession = RpcSession::make(); +#ifdef __BIONIC__ +static const String16 kKernelBinderInstance = String16(u"binderRpcBenchmark-control"); +static sp<IBinder> gKernelBinder; +#endif + +static sp<IBinder> getBinderForOptions(benchmark::State& state) { + Transport transport = static_cast<Transport>(state.range(0)); + switch (transport) { +#ifdef __BIONIC__ + case KERNEL: + return gKernelBinder; +#endif + case RPC: + return gSession->getRootObject(); + default: + LOG(FATAL) << "Unknown transport value: " << transport; + return nullptr; } } -BENCHMARK(BM_getRootObject); void BM_pingTransaction(benchmark::State& state) { - sp<IBinder> binder = gSession->getRootObject(); - CHECK(binder != nullptr); + sp<IBinder> binder = getBinderForOptions(state); while (state.KeepRunning()) { CHECK_EQ(OK, binder->pingBinder()); } } -BENCHMARK(BM_pingTransaction); +BENCHMARK(BM_pingTransaction)->Apply(EachTransport); void BM_repeatString(benchmark::State& state) { - sp<IBinder> binder = gSession->getRootObject(); - CHECK(binder != nullptr); + sp<IBinder> binder = getBinderForOptions(state); + sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder); CHECK(iface != nullptr); @@ -92,7 +124,7 @@ void BM_repeatString(benchmark::State& state) { CHECK(ret.isOk()) << ret; } } -BENCHMARK(BM_repeatString); +BENCHMARK(BM_repeatString)->Apply(EachTransport); void BM_repeatBinder(benchmark::State& state) { sp<IBinder> binder = gSession->getRootObject(); @@ -109,7 +141,7 @@ void BM_repeatBinder(benchmark::State& state) { CHECK(ret.isOk()) << ret; } } -BENCHMARK(BM_repeatBinder); +BENCHMARK(BM_repeatBinder)->Apply(EachTransport); int main(int argc, char** argv) { ::benchmark::Initialize(&argc, argv); @@ -118,6 +150,26 @@ int main(int argc, char** argv) { std::string addr = std::string(getenv("TMPDIR") ?: "/tmp") + "/binderRpcBenchmark"; (void)unlink(addr.c_str()); + std::cerr << "Tests suffixes:" << std::endl; + std::cerr << "\t\\" << Transport::KERNEL << " is KERNEL" << std::endl; + std::cerr << "\t\\" << Transport::RPC << " is RPC" << std::endl; + +#ifdef __BIONIC__ + if (0 == fork()) { + prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay + CHECK_EQ(OK, + defaultServiceManager()->addService(kKernelBinderInstance, + sp<MyBinderRpcBenchmark>::make())); + IPCThreadState::self()->joinThreadPool(); + } + + ProcessState::self()->setThreadPoolMaxThreadCount(1); + ProcessState::self()->startThreadPool(); + + gKernelBinder = defaultServiceManager()->waitForService(kKernelBinderInstance); + CHECK_NE(nullptr, gKernelBinder.get()); +#endif + std::thread([addr]() { sp<RpcServer> server = RpcServer::make(); server->setRootObject(sp<MyBinderRpcBenchmark>::make()); |