blob: 07cff885442d83ef6df34a02cfc1c66e6019f890 [file] [log] [blame]
Craig Tiller93d802b2016-10-25 21:05:49 -07001/*
2 *
3 * Copyright 2016, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34/* Benchmark gRPC end2end in various configurations */
35
36#include <sstream>
37
38#include <grpc++/channel.h>
39#include <grpc++/create_channel.h>
Craig Tiller1d0fce92016-10-26 08:26:22 -070040#include <grpc++/impl/grpc_library.h>
Craig Tiller93d802b2016-10-25 21:05:49 -070041#include <grpc++/security/credentials.h>
42#include <grpc++/security/server_credentials.h>
43#include <grpc++/server.h>
44#include <grpc++/server_builder.h>
45#include <grpc/support/log.h>
46
Craig Tiller1d0fce92016-10-26 08:26:22 -070047extern "C" {
48#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
49#include "src/core/lib/channel/channel_args.h"
50#include "src/core/lib/iomgr/endpoint.h"
51#include "src/core/lib/iomgr/endpoint_pair.h"
52#include "src/core/lib/iomgr/exec_ctx.h"
53#include "src/core/lib/iomgr/tcp_posix.h"
54#include "src/core/lib/surface/channel.h"
55#include "src/core/lib/surface/completion_queue.h"
56#include "src/core/lib/surface/server.h"
57#include "test/core/util/passthru_endpoint.h"
Craig Tiller93d802b2016-10-25 21:05:49 -070058#include "test/core/util/port.h"
Craig Tiller1d0fce92016-10-26 08:26:22 -070059}
60#include "src/cpp/client/create_channel_internal.h"
61#include "src/proto/grpc/testing/echo.grpc.pb.h"
Craig Tiller93d802b2016-10-25 21:05:49 -070062#include "third_party/google_benchmark/include/benchmark/benchmark.h"
63
64namespace grpc {
65namespace testing {
66
Craig Tiller1d0fce92016-10-26 08:26:22 -070067static class InitializeStuff {
68 public:
Craig Tiller63ec2932016-11-01 15:00:41 -070069 InitializeStuff() {
70 init_lib_.init();
71 rq_ = grpc_resource_quota_create("bm");
72 }
73
74 grpc_resource_quota* rq() { return rq_; }
Craig Tiller1d0fce92016-10-26 08:26:22 -070075
76 private:
Craig Tiller63ec2932016-11-01 15:00:41 -070077 internal::GrpcLibrary init_lib_;
78 grpc_resource_quota* rq_;
Craig Tiller1d0fce92016-10-26 08:26:22 -070079} initialize_stuff;
80
Craig Tiller93d802b2016-10-25 21:05:49 -070081/*******************************************************************************
82 * FIXTURES
83 */
84
Craig Tiller1d0fce92016-10-26 08:26:22 -070085class FullstackFixture {
Craig Tiller93d802b2016-10-25 21:05:49 -070086 public:
Craig Tiller1d0fce92016-10-26 08:26:22 -070087 FullstackFixture(Service* service, const grpc::string& address) {
Craig Tiller93d802b2016-10-25 21:05:49 -070088 ServerBuilder b;
Craig Tiller1d0fce92016-10-26 08:26:22 -070089 b.AddListeningPort(address, InsecureServerCredentials());
Craig Tiller93d802b2016-10-25 21:05:49 -070090 cq_ = b.AddCompletionQueue(true);
91 b.RegisterService(service);
92 server_ = b.BuildAndStart();
Craig Tiller1d0fce92016-10-26 08:26:22 -070093 channel_ = CreateChannel(address, InsecureChannelCredentials());
Craig Tiller93d802b2016-10-25 21:05:49 -070094 }
95
Craig Tillerb4d883b2016-11-01 15:10:22 -070096 virtual ~FullstackFixture() {
97 server_->Shutdown();
98 cq_->Shutdown();
99 void* tag;
100 bool ok;
101 while (cq_->Next(&tag, &ok)) {
102 }
103 }
104
Craig Tiller93d802b2016-10-25 21:05:49 -0700105 ServerCompletionQueue* cq() { return cq_.get(); }
Craig Tiller93d802b2016-10-25 21:05:49 -0700106 std::shared_ptr<Channel> channel() { return channel_; }
107
108 private:
109 std::unique_ptr<Server> server_;
110 std::unique_ptr<ServerCompletionQueue> cq_;
111 std::shared_ptr<Channel> channel_;
112};
113
Craig Tiller1d0fce92016-10-26 08:26:22 -0700114class TCP : public FullstackFixture {
115 public:
116 TCP(Service* service) : FullstackFixture(service, MakeAddress()) {}
117
118 private:
119 static grpc::string MakeAddress() {
120 int port = grpc_pick_unused_port_or_die();
121 std::stringstream addr;
122 addr << "localhost:" << port;
123 return addr.str();
124 }
125};
126
127class UDS : public FullstackFixture {
128 public:
129 UDS(Service* service) : FullstackFixture(service, "unix:bm_fullstack") {}
130};
131
132class EndpointPairFixture {
133 public:
134 EndpointPairFixture(Service* service, grpc_endpoint_pair endpoints) {
135 ServerBuilder b;
136 cq_ = b.AddCompletionQueue(true);
137 b.RegisterService(service);
138 server_ = b.BuildAndStart();
139
140 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
141
142 /* add server endpoint to server_ */
143 {
144 const grpc_channel_args* server_args =
145 grpc_server_get_channel_args(server_->c_server());
146 grpc_transport* transport = grpc_create_chttp2_transport(
147 &exec_ctx, server_args, endpoints.server, 0 /* is_client */);
148
149 grpc_pollset** pollsets;
150 size_t num_pollsets = 0;
151 grpc_server_get_pollsets(server_->c_server(), &pollsets, &num_pollsets);
152
153 for (size_t i = 0; i < num_pollsets; i++) {
154 grpc_endpoint_add_to_pollset(&exec_ctx, endpoints.server, pollsets[i]);
155 }
156
157 grpc_server_setup_transport(&exec_ctx, server_->c_server(), transport,
158 NULL, server_args);
159 grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL);
160 }
161
162 /* create channel */
163 {
164 ChannelArguments args;
165 args.SetString(GRPC_ARG_DEFAULT_AUTHORITY, "test.authority");
166
167 grpc_channel_args c_args = args.c_args();
168 grpc_transport* transport =
169 grpc_create_chttp2_transport(&exec_ctx, &c_args, endpoints.client, 1);
170 GPR_ASSERT(transport);
171 grpc_channel* channel = grpc_channel_create(
172 &exec_ctx, "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, transport);
173 grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL);
174
175 channel_ = CreateChannelInternal("", channel);
176 }
177
178 grpc_exec_ctx_finish(&exec_ctx);
179 }
180
Craig Tillerb4d883b2016-11-01 15:10:22 -0700181 virtual ~EndpointPairFixture() {
182 server_->Shutdown();
183 cq_->Shutdown();
184 void* tag;
185 bool ok;
186 while (cq_->Next(&tag, &ok)) {
187 }
188 }
189
Craig Tiller1d0fce92016-10-26 08:26:22 -0700190 ServerCompletionQueue* cq() { return cq_.get(); }
191 std::shared_ptr<Channel> channel() { return channel_; }
192
193 private:
194 std::unique_ptr<Server> server_;
195 std::unique_ptr<ServerCompletionQueue> cq_;
196 std::shared_ptr<Channel> channel_;
197};
198
199class SockPair : public EndpointPairFixture {
200 public:
201 SockPair(Service* service)
Craig Tiller63ec2932016-11-01 15:00:41 -0700202 : EndpointPairFixture(service, grpc_iomgr_create_endpoint_pair(
203 "test", initialize_stuff.rq(), 8192)) {
204 }
Craig Tiller1d0fce92016-10-26 08:26:22 -0700205};
206
207class InProcessCHTTP2 : public EndpointPairFixture {
208 public:
209 InProcessCHTTP2(Service* service)
210 : EndpointPairFixture(service, MakeEndpoints()) {}
211
212 private:
213 grpc_endpoint_pair MakeEndpoints() {
214 grpc_endpoint_pair p;
Craig Tiller63ec2932016-11-01 15:00:41 -0700215 grpc_passthru_endpoint_create(&p.client, &p.server, initialize_stuff.rq());
Craig Tiller1d0fce92016-10-26 08:26:22 -0700216 return p;
217 }
218};
219
Craig Tiller93d802b2016-10-25 21:05:49 -0700220/*******************************************************************************
221 * BENCHMARKING KERNELS
222 */
223
224static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
225
226template <class Fixture>
227static void BM_UnaryPingPong(benchmark::State& state) {
228 EchoTestService::AsyncService service;
Craig Tillerff8e43a2016-11-01 15:13:31 -0700229 std::unique_ptr<Fixture> fixture(new Fixture(&service));
Craig Tiller93d802b2016-10-25 21:05:49 -0700230 EchoRequest send_request;
231 EchoResponse send_response;
232 EchoResponse recv_response;
233 Status recv_status;
234 struct ServerEnv {
235 ServerContext ctx;
236 EchoRequest recv_request;
237 grpc::ServerAsyncResponseWriter<EchoResponse> response_writer;
238 ServerEnv() : response_writer(&ctx) {}
239 };
240 uint8_t server_env_buffer[2 * sizeof(ServerEnv)];
241 ServerEnv* server_env[2] = {
242 reinterpret_cast<ServerEnv*>(server_env_buffer),
243 reinterpret_cast<ServerEnv*>(server_env_buffer + sizeof(ServerEnv))};
244 new (server_env[0]) ServerEnv;
245 new (server_env[1]) ServerEnv;
246 service.RequestEcho(&server_env[0]->ctx, &server_env[0]->recv_request,
Craig Tillerff8e43a2016-11-01 15:13:31 -0700247 &server_env[0]->response_writer, fixture->cq(),
248 fixture->cq(), tag(0));
Craig Tiller93d802b2016-10-25 21:05:49 -0700249 service.RequestEcho(&server_env[1]->ctx, &server_env[1]->recv_request,
Craig Tillerff8e43a2016-11-01 15:13:31 -0700250 &server_env[1]->response_writer, fixture->cq(),
251 fixture->cq(), tag(1));
Craig Tiller93d802b2016-10-25 21:05:49 -0700252 std::unique_ptr<EchoTestService::Stub> stub(
Craig Tillerff8e43a2016-11-01 15:13:31 -0700253 EchoTestService::NewStub(fixture->channel()));
Craig Tiller93d802b2016-10-25 21:05:49 -0700254 while (state.KeepRunning()) {
255 ClientContext cli_ctx;
256 std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
Craig Tillerff8e43a2016-11-01 15:13:31 -0700257 stub->AsyncEcho(&cli_ctx, send_request, fixture->cq()));
Craig Tiller93d802b2016-10-25 21:05:49 -0700258 void* t;
259 bool ok;
Craig Tillerff8e43a2016-11-01 15:13:31 -0700260 GPR_ASSERT(fixture->cq()->Next(&t, &ok));
Craig Tiller93d802b2016-10-25 21:05:49 -0700261 GPR_ASSERT(ok);
262 GPR_ASSERT(t == tag(0) || t == tag(1));
263 intptr_t slot = reinterpret_cast<intptr_t>(t);
264 ServerEnv* senv = server_env[slot];
265 senv->response_writer.Finish(send_response, Status::OK, tag(3));
266 response_reader->Finish(&recv_response, &recv_status, tag(4));
267 for (int i = (1 << 3) | (1 << 4); i != 0;) {
Craig Tillerff8e43a2016-11-01 15:13:31 -0700268 GPR_ASSERT(fixture->cq()->Next(&t, &ok));
Craig Tiller93d802b2016-10-25 21:05:49 -0700269 GPR_ASSERT(ok);
270 int tagnum = (int)reinterpret_cast<intptr_t>(t);
271 GPR_ASSERT(i & (1 << tagnum));
272 i -= 1 << tagnum;
273 }
274 GPR_ASSERT(recv_status.ok());
275
276 senv->~ServerEnv();
277 senv = new (senv) ServerEnv();
278 service.RequestEcho(&senv->ctx, &senv->recv_request, &senv->response_writer,
Craig Tillerff8e43a2016-11-01 15:13:31 -0700279 fixture->cq(), fixture->cq(), tag(slot));
Craig Tiller93d802b2016-10-25 21:05:49 -0700280 }
Craig Tillerff8e43a2016-11-01 15:13:31 -0700281 fixture.reset();
Craig Tillerb4d883b2016-11-01 15:10:22 -0700282 server_env[0]->~ServerEnv();
283 server_env[1]->~ServerEnv();
Craig Tiller93d802b2016-10-25 21:05:49 -0700284}
285
286/*******************************************************************************
287 * CONFIGURATIONS
288 */
289
Craig Tiller1d0fce92016-10-26 08:26:22 -0700290BENCHMARK_TEMPLATE(BM_UnaryPingPong, TCP);
291BENCHMARK_TEMPLATE(BM_UnaryPingPong, UDS);
292BENCHMARK_TEMPLATE(BM_UnaryPingPong, SockPair);
293BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2);
Craig Tiller93d802b2016-10-25 21:05:49 -0700294
295} // namespace testing
296} // namespace grpc
297
298BENCHMARK_MAIN();