blob: 022808f290b3c3e87a6ede759737100393bd8060 [file] [log] [blame]
Josh Gao11e41d62018-04-04 11:27:24 -07001/*
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
Josh Gao358aca22018-04-04 17:53:54 -070017#include <malloc.h>
Josh Gao11e41d62018-04-04 11:27:24 -070018#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
Josh Gao1e41fda2018-04-05 16:16:04 -070027#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) \
Josh Gao11e41d62018-04-04 11:27:24 -070037 ->UseRealTime()
38
Josh Gao1e41fda2018-04-05 16:16:04 -070039struct NonblockingFdConnection;
Josh Gao11e41d62018-04-04 11:27:24 -070040template <typename ConnectionType>
41std::unique_ptr<Connection> MakeConnection(unique_fd fd);
42
43template <>
44std::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
Josh Gao1e41fda2018-04-05 16:16:04 -070049template <>
50std::unique_ptr<Connection> MakeConnection<NonblockingFdConnection>(unique_fd fd) {
51 return Connection::FromFd(std::move(fd));
52}
53
Josh Gao11e41d62018-04-04 11:27:24 -070054template <typename ConnectionType>
55void 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
102ADB_CONNECTION_BENCHMARK(BM_Connection_Unidirectional);
103
104enum class ThreadPolicy {
105 MainThread,
106 SameThread,
107};
108
109template <typename ConnectionType, enum ThreadPolicy Policy>
110void 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
182ADB_CONNECTION_BENCHMARK(BM_Connection_Echo, ThreadPolicy::SameThread);
183ADB_CONNECTION_BENCHMARK(BM_Connection_Echo, ThreadPolicy::MainThread);
184
185int main(int argc, char** argv) {
Josh Gao358aca22018-04-04 17:53:54 -0700186 // Set M_DECAY_TIME so that our allocations aren't immediately purged on free.
187 mallopt(M_DECAY_TIME, 1);
188
Josh Gao11e41d62018-04-04 11:27:24 -0700189 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}