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