| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 1 | /* | 
 | 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 Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 21 | #include <binder/IPCThreadState.h> | 
 | 22 | #include <binder/IServiceManager.h> | 
 | 23 | #include <binder/ProcessState.h> | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 24 | #include <binder/RpcServer.h> | 
| Steven Moreland | bdb53ab | 2021-05-05 17:57:41 +0000 | [diff] [blame] | 25 | #include <binder/RpcSession.h> | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 26 |  | 
 | 27 | #include <thread> | 
 | 28 |  | 
| Steven Moreland | 656e9d1 | 2021-07-29 17:33:53 -0700 | [diff] [blame] | 29 | #include <signal.h> | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 30 | #include <sys/prctl.h> | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 31 | #include <sys/types.h> | 
 | 32 | #include <unistd.h> | 
 | 33 |  | 
 | 34 | using android::BBinder; | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 35 | using android::defaultServiceManager; | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 36 | using android::IBinder; | 
 | 37 | using android::interface_cast; | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 38 | using android::IPCThreadState; | 
 | 39 | using android::IServiceManager; | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 40 | using android::OK; | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 41 | using android::ProcessState; | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 42 | using android::RpcServer; | 
| Steven Moreland | bdb53ab | 2021-05-05 17:57:41 +0000 | [diff] [blame] | 43 | using android::RpcSession; | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 44 | using android::sp; | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 45 | using android::String16; | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 46 | using android::binder::Status; | 
 | 47 |  | 
 | 48 | class MyBinderRpcBenchmark : public BnBinderRpcBenchmark { | 
 | 49 |     Status repeatString(const std::string& str, std::string* out) override { | 
 | 50 |         *out = str; | 
 | 51 |         return Status::ok(); | 
 | 52 |     } | 
 | 53 |     Status repeatBinder(const sp<IBinder>& str, sp<IBinder>* out) override { | 
 | 54 |         *out = str; | 
 | 55 |         return Status::ok(); | 
 | 56 |     } | 
 | 57 | }; | 
 | 58 |  | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 59 | enum Transport { | 
 | 60 |     KERNEL, | 
 | 61 |     RPC, | 
 | 62 | }; | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 63 |  | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 64 | static void EachTransport(benchmark::internal::Benchmark* b) { | 
 | 65 | #ifdef __BIONIC__ | 
 | 66 |     b->Args({Transport::KERNEL}); | 
 | 67 | #endif | 
 | 68 |     b->Args({Transport::RPC}); | 
 | 69 | } | 
 | 70 |  | 
 | 71 | static sp<RpcSession> gSession = RpcSession::make(); | 
 | 72 | #ifdef __BIONIC__ | 
 | 73 | static const String16 kKernelBinderInstance = String16(u"binderRpcBenchmark-control"); | 
 | 74 | static sp<IBinder> gKernelBinder; | 
 | 75 | #endif | 
 | 76 |  | 
 | 77 | static sp<IBinder> getBinderForOptions(benchmark::State& state) { | 
 | 78 |     Transport transport = static_cast<Transport>(state.range(0)); | 
 | 79 |     switch (transport) { | 
 | 80 | #ifdef __BIONIC__ | 
 | 81 |         case KERNEL: | 
 | 82 |             return gKernelBinder; | 
 | 83 | #endif | 
 | 84 |         case RPC: | 
 | 85 |             return gSession->getRootObject(); | 
 | 86 |         default: | 
 | 87 |             LOG(FATAL) << "Unknown transport value: " << transport; | 
 | 88 |             return nullptr; | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 89 |     } | 
 | 90 | } | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 91 |  | 
 | 92 | void BM_pingTransaction(benchmark::State& state) { | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 93 |     sp<IBinder> binder = getBinderForOptions(state); | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 94 |  | 
 | 95 |     while (state.KeepRunning()) { | 
 | 96 |         CHECK_EQ(OK, binder->pingBinder()); | 
 | 97 |     } | 
 | 98 | } | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 99 | BENCHMARK(BM_pingTransaction)->Apply(EachTransport); | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 100 |  | 
 | 101 | void BM_repeatString(benchmark::State& state) { | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 102 |     sp<IBinder> binder = getBinderForOptions(state); | 
 | 103 |  | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 104 |     sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder); | 
 | 105 |     CHECK(iface != nullptr); | 
 | 106 |  | 
 | 107 |     // Googlers might see go/another-look-at-aidl-hidl-perf | 
 | 108 |     // | 
 | 109 |     // When I checked in July 2019, 99.5% of AIDL transactions and 99.99% of HIDL | 
 | 110 |     // transactions were less than one page in size (system wide during a test | 
 | 111 |     // involving media and camera). This is why this diverges from | 
 | 112 |     // binderThroughputTest and hwbinderThroughputTest. Future consideration - get | 
 | 113 |     // this data on continuous integration. Here we are testing sending a | 
 | 114 |     // transaction of twice this size. In other cases, we should focus on | 
 | 115 |     // benchmarks of particular usecases. If individual binder transactions like | 
 | 116 |     // the ones tested here are fast, then Android performance will be dominated | 
 | 117 |     // by how many binder calls work together (and by factors like the scheduler, | 
 | 118 |     // thermal throttling, core choice, etc..). | 
 | 119 |     std::string str = std::string(getpagesize() * 2, 'a'); | 
 | 120 |     CHECK_EQ(str.size(), getpagesize() * 2); | 
 | 121 |  | 
 | 122 |     while (state.KeepRunning()) { | 
 | 123 |         std::string out; | 
 | 124 |         Status ret = iface->repeatString(str, &out); | 
 | 125 |         CHECK(ret.isOk()) << ret; | 
 | 126 |     } | 
 | 127 | } | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 128 | BENCHMARK(BM_repeatString)->Apply(EachTransport); | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 129 |  | 
 | 130 | void BM_repeatBinder(benchmark::State& state) { | 
| Steven Moreland | bdb53ab | 2021-05-05 17:57:41 +0000 | [diff] [blame] | 131 |     sp<IBinder> binder = gSession->getRootObject(); | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 132 |     CHECK(binder != nullptr); | 
 | 133 |     sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder); | 
 | 134 |     CHECK(iface != nullptr); | 
 | 135 |  | 
 | 136 |     while (state.KeepRunning()) { | 
 | 137 |         // force creation of a new address | 
 | 138 |         sp<IBinder> binder = sp<BBinder>::make(); | 
 | 139 |  | 
 | 140 |         sp<IBinder> out; | 
 | 141 |         Status ret = iface->repeatBinder(binder, &out); | 
 | 142 |         CHECK(ret.isOk()) << ret; | 
 | 143 |     } | 
 | 144 | } | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 145 | BENCHMARK(BM_repeatBinder)->Apply(EachTransport); | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 146 |  | 
 | 147 | int main(int argc, char** argv) { | 
 | 148 |     ::benchmark::Initialize(&argc, argv); | 
 | 149 |     if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; | 
 | 150 |  | 
 | 151 |     std::string addr = std::string(getenv("TMPDIR") ?: "/tmp") + "/binderRpcBenchmark"; | 
 | 152 |     (void)unlink(addr.c_str()); | 
 | 153 |  | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 154 |     std::cerr << "Tests suffixes:" << std::endl; | 
 | 155 |     std::cerr << "\t\\" << Transport::KERNEL << " is KERNEL" << std::endl; | 
 | 156 |     std::cerr << "\t\\" << Transport::RPC << " is RPC" << std::endl; | 
 | 157 |  | 
| Steven Moreland | 656e9d1 | 2021-07-29 17:33:53 -0700 | [diff] [blame] | 158 |     if (0 == fork()) { | 
 | 159 |         prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay | 
 | 160 |         sp<RpcServer> server = RpcServer::make(); | 
 | 161 |         server->setRootObject(sp<MyBinderRpcBenchmark>::make()); | 
 | 162 |         server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); | 
 | 163 |         CHECK(server->setupUnixDomainServer(addr.c_str())); | 
 | 164 |         server->join(); | 
 | 165 |         exit(1); | 
 | 166 |     } | 
 | 167 |  | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 168 | #ifdef __BIONIC__ | 
 | 169 |     if (0 == fork()) { | 
 | 170 |         prctl(PR_SET_PDEATHSIG, SIGHUP); // racey, okay | 
 | 171 |         CHECK_EQ(OK, | 
 | 172 |                  defaultServiceManager()->addService(kKernelBinderInstance, | 
 | 173 |                                                      sp<MyBinderRpcBenchmark>::make())); | 
 | 174 |         IPCThreadState::self()->joinThreadPool(); | 
| Steven Moreland | 656e9d1 | 2021-07-29 17:33:53 -0700 | [diff] [blame] | 175 |         exit(1); | 
| Steven Moreland | 1ebdc70 | 2021-07-28 18:46:15 -0700 | [diff] [blame] | 176 |     } | 
 | 177 |  | 
 | 178 |     ProcessState::self()->setThreadPoolMaxThreadCount(1); | 
 | 179 |     ProcessState::self()->startThreadPool(); | 
 | 180 |  | 
 | 181 |     gKernelBinder = defaultServiceManager()->waitForService(kKernelBinderInstance); | 
 | 182 |     CHECK_NE(nullptr, gKernelBinder.get()); | 
 | 183 | #endif | 
 | 184 |  | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 185 |     for (size_t tries = 0; tries < 5; tries++) { | 
 | 186 |         usleep(10000); | 
| Steven Moreland | bdb53ab | 2021-05-05 17:57:41 +0000 | [diff] [blame] | 187 |         if (gSession->setupUnixDomainClient(addr.c_str())) goto success; | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 188 |     } | 
 | 189 |     LOG(FATAL) << "Could not connect."; | 
 | 190 | success: | 
 | 191 |  | 
 | 192 |     ::benchmark::RunSpecifiedBenchmarks(); | 
| Steven Moreland | 3ae982a | 2021-05-05 18:16:11 +0000 | [diff] [blame] | 193 |     return 0; | 
| Steven Moreland | cda6085 | 2021-04-14 23:45:32 +0000 | [diff] [blame] | 194 | } |