3 * Copyright 2017 gRPC authors.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #ifndef TEST_CPP_MICROBENCHMARKS_FULLSTACK_FIXTURES_H
20 #define TEST_CPP_MICROBENCHMARKS_FULLSTACK_FIXTURES_H
22 #include <grpc/support/atm.h>
23 #include <grpc/support/log.h>
24 #include <grpcpp/channel.h>
25 #include <grpcpp/create_channel.h>
26 #include <grpcpp/security/credentials.h>
27 #include <grpcpp/security/server_credentials.h>
28 #include <grpcpp/server.h>
29 #include <grpcpp/server_builder.h>
31 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
32 #include "src/core/lib/channel/channel_args.h"
33 #include "src/core/lib/iomgr/endpoint.h"
34 #include "src/core/lib/iomgr/endpoint_pair.h"
35 #include "src/core/lib/iomgr/exec_ctx.h"
36 #include "src/core/lib/iomgr/tcp_posix.h"
37 #include "src/core/lib/surface/channel.h"
38 #include "src/core/lib/surface/completion_queue.h"
39 #include "src/core/lib/surface/server.h"
40 #include "test/core/util/passthru_endpoint.h"
41 #include "test/core/util/port.h"
43 #include "src/cpp/client/create_channel_internal.h"
44 #include "test/cpp/microbenchmarks/helpers.h"
49 class FixtureConfiguration {
51 virtual ~FixtureConfiguration() {}
52 virtual void ApplyCommonChannelArguments(ChannelArguments* c) const {
53 c->SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, INT_MAX);
54 c->SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, INT_MAX);
57 virtual void ApplyCommonServerBuilderConfig(ServerBuilder* b) const {
58 b->SetMaxReceiveMessageSize(INT_MAX);
59 b->SetMaxSendMessageSize(INT_MAX);
63 class BaseFixture : public TrackCounters {};
65 class FullstackFixture : public BaseFixture {
67 FullstackFixture(Service* service, const FixtureConfiguration& config,
68 const std::string& address) {
70 if (address.length() > 0) {
71 b.AddListeningPort(address, InsecureServerCredentials());
73 cq_ = b.AddCompletionQueue(true);
74 b.RegisterService(service);
75 config.ApplyCommonServerBuilderConfig(&b);
76 server_ = b.BuildAndStart();
77 ChannelArguments args;
78 config.ApplyCommonChannelArguments(&args);
79 if (address.length() > 0) {
80 channel_ = ::grpc::CreateCustomChannel(
81 address, InsecureChannelCredentials(), args);
83 channel_ = server_->InProcessChannel(args);
87 virtual ~FullstackFixture() {
92 while (cq_->Next(&tag, &ok)) {
96 void AddToLabel(std::ostream& out, benchmark::State& state) {
97 BaseFixture::AddToLabel(out, state);
99 << static_cast<double>(grpc_get_cq_poll_num(this->cq()->cq())) /
103 ServerCompletionQueue* cq() { return cq_.get(); }
104 std::shared_ptr<Channel> channel() { return channel_; }
107 std::unique_ptr<Server> server_;
108 std::unique_ptr<ServerCompletionQueue> cq_;
109 std::shared_ptr<Channel> channel_;
112 class TCP : public FullstackFixture {
114 TCP(Service* service, const FixtureConfiguration& fixture_configuration =
115 FixtureConfiguration())
116 : FullstackFixture(service, fixture_configuration, MakeAddress(&port_)) {}
118 ~TCP() { grpc_recycle_unused_port(port_); }
123 static std::string MakeAddress(int* port) {
124 *port = grpc_pick_unused_port_or_die();
125 std::stringstream addr;
126 addr << "localhost:" << *port;
131 class UDS : public FullstackFixture {
133 UDS(Service* service, const FixtureConfiguration& fixture_configuration =
134 FixtureConfiguration())
135 : FullstackFixture(service, fixture_configuration, MakeAddress(&port_)) {}
137 ~UDS() { grpc_recycle_unused_port(port_); }
142 static std::string MakeAddress(int* port) {
143 *port = grpc_pick_unused_port_or_die(); // just for a unique id - not a
145 std::stringstream addr;
146 addr << "unix:/tmp/bm_fullstack." << *port;
151 class InProcess : public FullstackFixture {
153 InProcess(Service* service,
154 const FixtureConfiguration& fixture_configuration =
155 FixtureConfiguration())
156 : FullstackFixture(service, fixture_configuration, "") {}
160 class EndpointPairFixture : public BaseFixture {
162 EndpointPairFixture(Service* service, grpc_endpoint_pair endpoints,
163 const FixtureConfiguration& fixture_configuration)
164 : endpoint_pair_(endpoints) {
166 cq_ = b.AddCompletionQueue(true);
167 b.RegisterService(service);
168 fixture_configuration.ApplyCommonServerBuilderConfig(&b);
169 server_ = b.BuildAndStart();
171 grpc_core::ExecCtx exec_ctx;
173 /* add server endpoint to server_
176 const grpc_channel_args* server_args =
177 server_->c_server()->core_server->channel_args();
178 server_transport_ = grpc_create_chttp2_transport(
179 server_args, endpoints.server, false /* is_client */);
181 for (grpc_pollset* pollset :
182 server_->c_server()->core_server->pollsets()) {
183 grpc_endpoint_add_to_pollset(endpoints.server, pollset);
186 server_->c_server()->core_server->SetupTransport(
187 server_transport_, nullptr, server_args, nullptr);
188 grpc_chttp2_transport_start_reading(server_transport_, nullptr, nullptr);
193 ChannelArguments args;
194 args.SetString(GRPC_ARG_DEFAULT_AUTHORITY, "test.authority");
195 fixture_configuration.ApplyCommonChannelArguments(&args);
197 grpc_channel_args c_args = args.c_channel_args();
199 grpc_create_chttp2_transport(&c_args, endpoints.client, true);
200 GPR_ASSERT(client_transport_);
201 grpc_channel* channel = grpc_channel_create(
202 "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, client_transport_);
203 grpc_chttp2_transport_start_reading(client_transport_, nullptr, nullptr);
205 channel_ = ::grpc::CreateChannelInternal(
207 std::vector<std::unique_ptr<
208 experimental::ClientInterceptorFactoryInterface>>());
212 virtual ~EndpointPairFixture() {
217 while (cq_->Next(&tag, &ok)) {
221 void AddToLabel(std::ostream& out, benchmark::State& state) {
222 BaseFixture::AddToLabel(out, state);
223 out << " polls/iter:"
224 << static_cast<double>(grpc_get_cq_poll_num(this->cq()->cq())) /
228 ServerCompletionQueue* cq() { return cq_.get(); }
229 std::shared_ptr<Channel> channel() { return channel_; }
232 grpc_endpoint_pair endpoint_pair_;
233 grpc_transport* client_transport_;
234 grpc_transport* server_transport_;
237 std::unique_ptr<Server> server_;
238 std::unique_ptr<ServerCompletionQueue> cq_;
239 std::shared_ptr<Channel> channel_;
242 class SockPair : public EndpointPairFixture {
244 SockPair(Service* service, const FixtureConfiguration& fixture_configuration =
245 FixtureConfiguration())
246 : EndpointPairFixture(service,
247 grpc_iomgr_create_endpoint_pair("test", nullptr),
248 fixture_configuration) {}
251 /* Use InProcessCHTTP2 instead. This class (with stats as an explicit parameter)
252 is here only to be able to initialize both the base class and stats_ with the
253 same stats instance without accessing the stats_ fields before the object is
254 properly initialized. */
255 class InProcessCHTTP2WithExplicitStats : public EndpointPairFixture {
257 InProcessCHTTP2WithExplicitStats(
258 Service* service, grpc_passthru_endpoint_stats* stats,
259 const FixtureConfiguration& fixture_configuration)
260 : EndpointPairFixture(service, MakeEndpoints(stats),
261 fixture_configuration),
264 virtual ~InProcessCHTTP2WithExplicitStats() {
265 if (stats_ != nullptr) {
266 grpc_passthru_endpoint_stats_destroy(stats_);
270 void AddToLabel(std::ostream& out, benchmark::State& state) {
271 EndpointPairFixture::AddToLabel(out, state);
272 out << " writes/iter:"
273 << static_cast<double>(gpr_atm_no_barrier_load(&stats_->num_writes)) /
274 static_cast<double>(state.iterations());
278 grpc_passthru_endpoint_stats* stats_;
280 static grpc_endpoint_pair MakeEndpoints(grpc_passthru_endpoint_stats* stats) {
281 grpc_endpoint_pair p;
282 grpc_passthru_endpoint_create(&p.client, &p.server,
283 LibraryInitializer::get().rq(), stats);
288 class InProcessCHTTP2 : public InProcessCHTTP2WithExplicitStats {
290 InProcessCHTTP2(Service* service,
291 const FixtureConfiguration& fixture_configuration =
292 FixtureConfiguration())
293 : InProcessCHTTP2WithExplicitStats(service,
294 grpc_passthru_endpoint_stats_create(),
295 fixture_configuration) {}
298 ////////////////////////////////////////////////////////////////////////////////
299 // Minimal stack fixtures
301 class MinStackConfiguration : public FixtureConfiguration {
302 void ApplyCommonChannelArguments(ChannelArguments* a) const override {
303 a->SetInt(GRPC_ARG_MINIMAL_STACK, 1);
304 FixtureConfiguration::ApplyCommonChannelArguments(a);
307 void ApplyCommonServerBuilderConfig(ServerBuilder* b) const override {
308 b->AddChannelArgument(GRPC_ARG_MINIMAL_STACK, 1);
309 FixtureConfiguration::ApplyCommonServerBuilderConfig(b);
313 template <class Base>
314 class MinStackize : public Base {
316 MinStackize(Service* service) : Base(service, MinStackConfiguration()) {}
319 typedef MinStackize<TCP> MinTCP;
320 typedef MinStackize<UDS> MinUDS;
321 typedef MinStackize<InProcess> MinInProcess;
322 typedef MinStackize<SockPair> MinSockPair;
323 typedef MinStackize<InProcessCHTTP2> MinInProcessCHTTP2;
325 } // namespace testing