• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <>
MakeConnection(unique_fd fd)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 <>
MakeConnection(unique_fd fd)50 std::unique_ptr<Connection> MakeConnection<NonblockingFdConnection>(unique_fd fd) {
51     return Connection::FromFd(std::move(fd));
52 }
53 
54 template <typename ConnectionType>
BM_Connection_Unidirectional(benchmark::State & state)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>
BM_Connection_Echo(benchmark::State & state)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 
main(int argc,char ** argv)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