1 /* 2 * Copyright (C) 2018 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 <malloc.h> 18 #include <stdio.h> 19 20 #include <android-base/logging.h> 21 #include <benchmark/benchmark.h> 22 23 #include "adb_trace.h" 24 #include "sysdeps.h" 25 #include "transport.h" 26 27 #define ADB_CONNECTION_BENCHMARK(benchmark_name, ...) \ 28 BENCHMARK_TEMPLATE(benchmark_name, FdConnection, ##__VA_ARGS__) \ 29 ->Arg(1) \ 30 ->Arg(16384) \ 31 ->Arg(MAX_PAYLOAD) \ 32 ->UseRealTime(); \ 33 BENCHMARK_TEMPLATE(benchmark_name, NonblockingFdConnection, ##__VA_ARGS__) \ 34 ->Arg(1) \ 35 ->Arg(16384) \ 36 ->Arg(MAX_PAYLOAD) \ 37 ->UseRealTime() 38 39 struct NonblockingFdConnection; 40 template <typename ConnectionType> 41 std::unique_ptr<Connection> MakeConnection(unique_fd fd); 42 43 template <> 44 std::unique_ptr<Connection> MakeConnection<FdConnection>(unique_fd fd) { 45 auto fd_connection = std::make_unique<FdConnection>(std::move(fd)); 46 return std::make_unique<BlockingConnectionAdapter>(std::move(fd_connection)); 47 } 48 49 template <> 50 std::unique_ptr<Connection> MakeConnection<NonblockingFdConnection>(unique_fd fd) { 51 return Connection::FromFd(std::move(fd)); 52 } 53 54 template <typename ConnectionType> 55 void BM_Connection_Unidirectional(benchmark::State& state) { 56 int fds[2]; 57 if (adb_socketpair(fds) != 0) { 58 LOG(FATAL) << "failed to create socketpair"; 59 } 60 61 auto client = MakeConnection<ConnectionType>(unique_fd(fds[0])); 62 auto server = MakeConnection<ConnectionType>(unique_fd(fds[1])); 63 64 std::atomic<size_t> received_bytes; 65 66 client->SetReadCallback([](Connection*, std::unique_ptr<apacket>) -> bool { return true; }); 67 server->SetReadCallback([&received_bytes](Connection*, std::unique_ptr<apacket> packet) -> bool { 68 received_bytes += packet->payload.size(); 69 return true; 70 }); 71 72 client->SetErrorCallback( 73 [](Connection*, const std::string& error) { LOG(INFO) << "client closed: " << error; }); 74 server->SetErrorCallback( 75 [](Connection*, const std::string& error) { LOG(INFO) << "server closed: " << error; }); 76 77 client->Start(); 78 server->Start(); 79 80 for (auto _ : state) { 81 size_t data_size = state.range(0); 82 std::unique_ptr<apacket> packet = std::make_unique<apacket>(); 83 memset(&packet->msg, 0, sizeof(packet->msg)); 84 packet->msg.command = A_WRTE; 85 packet->msg.data_length = data_size; 86 packet->payload.resize(data_size); 87 88 memset(&packet->payload[0], 0xff, data_size); 89 90 received_bytes = 0; 91 client->Write(std::move(packet)); 92 while (received_bytes < data_size) { 93 continue; 94 } 95 } 96 state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * state.range(0)); 97 98 client->Stop(); 99 server->Stop(); 100 } 101 102 ADB_CONNECTION_BENCHMARK(BM_Connection_Unidirectional); 103 104 enum class ThreadPolicy { 105 MainThread, 106 SameThread, 107 }; 108 109 template <typename ConnectionType, enum ThreadPolicy Policy> 110 void BM_Connection_Echo(benchmark::State& state) { 111 int fds[2]; 112 if (adb_socketpair(fds) != 0) { 113 LOG(FATAL) << "failed to create socketpair"; 114 } 115 116 auto client = MakeConnection<ConnectionType>(unique_fd(fds[0])); 117 auto server = MakeConnection<ConnectionType>(unique_fd(fds[1])); 118 119 std::atomic<size_t> received_bytes; 120 121 fdevent_reset(); 122 std::thread fdevent_thread([]() { fdevent_loop(); }); 123 124 client->SetReadCallback([&received_bytes](Connection*, std::unique_ptr<apacket> packet) -> bool { 125 received_bytes += packet->payload.size(); 126 return true; 127 }); 128 129 static const auto handle_packet = [](Connection* connection, std::unique_ptr<apacket> packet) { 130 connection->Write(std::move(packet)); 131 }; 132 133 server->SetReadCallback([](Connection* connection, std::unique_ptr<apacket> packet) -> bool { 134 if (Policy == ThreadPolicy::MainThread) { 135 auto raw_packet = packet.release(); 136 fdevent_run_on_main_thread([connection, raw_packet]() { 137 std::unique_ptr<apacket> packet(raw_packet); 138 handle_packet(connection, std::move(packet)); 139 }); 140 } else { 141 handle_packet(connection, std::move(packet)); 142 } 143 return true; 144 }); 145 146 client->SetErrorCallback( 147 [](Connection*, const std::string& error) { LOG(INFO) << "client closed: " << error; }); 148 server->SetErrorCallback( 149 [](Connection*, const std::string& error) { LOG(INFO) << "server closed: " << error; }); 150 151 client->Start(); 152 server->Start(); 153 154 for (auto _ : state) { 155 size_t data_size = state.range(0); 156 std::unique_ptr<apacket> packet = std::make_unique<apacket>(); 157 memset(&packet->msg, 0, sizeof(packet->msg)); 158 packet->msg.command = A_WRTE; 159 packet->msg.data_length = data_size; 160 packet->payload.resize(data_size); 161 162 memset(&packet->payload[0], 0xff, data_size); 163 164 received_bytes = 0; 165 client->Write(std::move(packet)); 166 while (received_bytes < data_size) { 167 continue; 168 } 169 } 170 state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) * state.range(0)); 171 172 client->Stop(); 173 server->Stop(); 174 175 // TODO: Make it so that you don't need to poke the fdevent loop to make it terminate? 176 fdevent_terminate_loop(); 177 fdevent_run_on_main_thread([]() {}); 178 179 fdevent_thread.join(); 180 } 181 182 ADB_CONNECTION_BENCHMARK(BM_Connection_Echo, ThreadPolicy::SameThread); 183 ADB_CONNECTION_BENCHMARK(BM_Connection_Echo, ThreadPolicy::MainThread); 184 185 int main(int argc, char** argv) { 186 // Set M_DECAY_TIME so that our allocations aren't immediately purged on free. 187 mallopt(M_DECAY_TIME, 1); 188 189 android::base::SetMinimumLogSeverity(android::base::WARNING); 190 adb_trace_init(argv); 191 ::benchmark::Initialize(&argc, argv); 192 if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; 193 ::benchmark::RunSpecifiedBenchmarks(); 194 } 195