/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include using android::BBinder; using android::IBinder; using android::interface_cast; using android::OK; using android::RpcServer; using android::RpcSession; using android::sp; using android::binder::Status; class MyBinderRpcBenchmark : public BnBinderRpcBenchmark { Status repeatString(const std::string& str, std::string* out) override { *out = str; return Status::ok(); } Status repeatBinder(const sp& str, sp* out) override { *out = str; return Status::ok(); } }; static sp gSession = RpcSession::make(); void BM_getRootObject(benchmark::State& state) { while (state.KeepRunning()) { CHECK(gSession->getRootObject() != nullptr); } } BENCHMARK(BM_getRootObject); void BM_pingTransaction(benchmark::State& state) { sp binder = gSession->getRootObject(); CHECK(binder != nullptr); while (state.KeepRunning()) { CHECK_EQ(OK, binder->pingBinder()); } } BENCHMARK(BM_pingTransaction); void BM_repeatString(benchmark::State& state) { sp binder = gSession->getRootObject(); CHECK(binder != nullptr); sp iface = interface_cast(binder); CHECK(iface != nullptr); // Googlers might see go/another-look-at-aidl-hidl-perf // // When I checked in July 2019, 99.5% of AIDL transactions and 99.99% of HIDL // transactions were less than one page in size (system wide during a test // involving media and camera). This is why this diverges from // binderThroughputTest and hwbinderThroughputTest. Future consideration - get // this data on continuous integration. Here we are testing sending a // transaction of twice this size. In other cases, we should focus on // benchmarks of particular usecases. If individual binder transactions like // the ones tested here are fast, then Android performance will be dominated // by how many binder calls work together (and by factors like the scheduler, // thermal throttling, core choice, etc..). std::string str = std::string(getpagesize() * 2, 'a'); CHECK_EQ(str.size(), getpagesize() * 2); while (state.KeepRunning()) { std::string out; Status ret = iface->repeatString(str, &out); CHECK(ret.isOk()) << ret; } } BENCHMARK(BM_repeatString); void BM_repeatBinder(benchmark::State& state) { sp binder = gSession->getRootObject(); CHECK(binder != nullptr); sp iface = interface_cast(binder); CHECK(iface != nullptr); while (state.KeepRunning()) { // force creation of a new address sp binder = sp::make(); sp out; Status ret = iface->repeatBinder(binder, &out); CHECK(ret.isOk()) << ret; } } BENCHMARK(BM_repeatBinder); int main(int argc, char** argv) { ::benchmark::Initialize(&argc, argv); if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; std::string addr = std::string(getenv("TMPDIR") ?: "/tmp") + "/binderRpcBenchmark"; (void)unlink(addr.c_str()); std::thread([addr]() { sp server = RpcServer::make(); server->setRootObject(sp::make()); server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); CHECK(server->setupUnixDomainServer(addr.c_str())); server->join(); }).detach(); for (size_t tries = 0; tries < 5; tries++) { usleep(10000); if (gSession->setupUnixDomainClient(addr.c_str())) goto success; } LOG(FATAL) << "Could not connect."; success: ::benchmark::RunSpecifiedBenchmarks(); return 0; }