08ff75ad8f9efc0a123eec03ebb0c25029a4bab0
[platform/upstream/grpc.git] / test / cpp / microbenchmarks / fullstack_fixtures.h
1 /*
2  *
3  * Copyright 2017 gRPC authors.
4  *
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  */
18
19 #ifndef TEST_CPP_MICROBENCHMARKS_FULLSTACK_FIXTURES_H
20 #define TEST_CPP_MICROBENCHMARKS_FULLSTACK_FIXTURES_H
21
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>
30
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 "src/cpp/client/create_channel_internal.h"
41 #include "test/core/util/passthru_endpoint.h"
42 #include "test/core/util/port.h"
43 #include "test/cpp/microbenchmarks/helpers.h"
44
45 namespace grpc {
46 namespace testing {
47
48 class FixtureConfiguration {
49  public:
50   virtual ~FixtureConfiguration() {}
51   virtual void ApplyCommonChannelArguments(ChannelArguments* c) const {
52     c->SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, INT_MAX);
53     c->SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, INT_MAX);
54   }
55
56   virtual void ApplyCommonServerBuilderConfig(ServerBuilder* b) const {
57     b->SetMaxReceiveMessageSize(INT_MAX);
58     b->SetMaxSendMessageSize(INT_MAX);
59   }
60 };
61
62 class BaseFixture : public TrackCounters {};
63
64 class FullstackFixture : public BaseFixture {
65  public:
66   FullstackFixture(Service* service, const FixtureConfiguration& config,
67                    const std::string& address) {
68     ServerBuilder b;
69     if (address.length() > 0) {
70       b.AddListeningPort(address, InsecureServerCredentials());
71     }
72     cq_ = b.AddCompletionQueue(true);
73     b.RegisterService(service);
74     config.ApplyCommonServerBuilderConfig(&b);
75     server_ = b.BuildAndStart();
76     ChannelArguments args;
77     config.ApplyCommonChannelArguments(&args);
78     if (address.length() > 0) {
79       channel_ = ::grpc::CreateCustomChannel(
80           address, InsecureChannelCredentials(), args);
81     } else {
82       channel_ = server_->InProcessChannel(args);
83     }
84   }
85
86   ~FullstackFixture() override {
87     server_->Shutdown();
88     cq_->Shutdown();
89     void* tag;
90     bool ok;
91     while (cq_->Next(&tag, &ok)) {
92     }
93   }
94
95   void AddToLabel(std::ostream& out, benchmark::State& state) override {
96     BaseFixture::AddToLabel(out, state);
97     out << " polls/iter:"
98         << static_cast<double>(grpc_get_cq_poll_num(this->cq()->cq())) /
99                state.iterations();
100   }
101
102   ServerCompletionQueue* cq() { return cq_.get(); }
103   std::shared_ptr<Channel> channel() { return channel_; }
104
105  private:
106   std::unique_ptr<Server> server_;
107   std::unique_ptr<ServerCompletionQueue> cq_;
108   std::shared_ptr<Channel> channel_;
109 };
110
111 class TCP : public FullstackFixture {
112  public:
113   explicit TCP(Service* service,
114                const FixtureConfiguration& fixture_configuration =
115                    FixtureConfiguration())
116       : FullstackFixture(service, fixture_configuration, MakeAddress(&port_)) {}
117
118   ~TCP() override { grpc_recycle_unused_port(port_); }
119
120  private:
121   int port_;
122
123   static std::string MakeAddress(int* port) {
124     *port = grpc_pick_unused_port_or_die();
125     std::stringstream addr;
126     addr << "localhost:" << *port;
127     return addr.str();
128   }
129 };
130
131 class UDS : public FullstackFixture {
132  public:
133   explicit UDS(Service* service,
134                const FixtureConfiguration& fixture_configuration =
135                    FixtureConfiguration())
136       : FullstackFixture(service, fixture_configuration, MakeAddress(&port_)) {}
137
138   ~UDS() override { grpc_recycle_unused_port(port_); }
139
140  private:
141   int port_;
142
143   static std::string MakeAddress(int* port) {
144     *port = grpc_pick_unused_port_or_die();  // just for a unique id - not a
145                                              // real port
146     std::stringstream addr;
147     addr << "unix:/tmp/bm_fullstack." << *port;
148     return addr.str();
149   }
150 };
151
152 class InProcess : public FullstackFixture {
153  public:
154   explicit InProcess(Service* service,
155                      const FixtureConfiguration& fixture_configuration =
156                          FixtureConfiguration())
157       : FullstackFixture(service, fixture_configuration, "") {}
158   ~InProcess() override {}
159 };
160
161 class EndpointPairFixture : public BaseFixture {
162  public:
163   EndpointPairFixture(Service* service, grpc_endpoint_pair endpoints,
164                       const FixtureConfiguration& fixture_configuration)
165       : endpoint_pair_(endpoints) {
166     ServerBuilder b;
167     cq_ = b.AddCompletionQueue(true);
168     b.RegisterService(service);
169     fixture_configuration.ApplyCommonServerBuilderConfig(&b);
170     server_ = b.BuildAndStart();
171     grpc_core::ExecCtx exec_ctx;
172     /* add server endpoint to server_
173      * */
174     {
175       const grpc_channel_args* server_args =
176           server_->c_server()->core_server->channel_args();
177       grpc_resource_quota* server_resource_quota =
178           grpc_resource_quota_from_channel_args(server_args, true);
179       server_transport_ = grpc_create_chttp2_transport(
180           server_args, endpoints.server, false /* is_client */,
181           grpc_resource_user_create(server_resource_quota, "server_transport"));
182       grpc_resource_quota_unref(server_resource_quota);
183       for (grpc_pollset* pollset :
184            server_->c_server()->core_server->pollsets()) {
185         grpc_endpoint_add_to_pollset(endpoints.server, pollset);
186       }
187
188       server_->c_server()->core_server->SetupTransport(
189           server_transport_, nullptr, server_args, nullptr);
190       grpc_chttp2_transport_start_reading(server_transport_, nullptr, nullptr,
191                                           nullptr);
192     }
193
194     /* create channel */
195     {
196       ChannelArguments args;
197       args.SetString(GRPC_ARG_DEFAULT_AUTHORITY, "test.authority");
198       fixture_configuration.ApplyCommonChannelArguments(&args);
199
200       grpc_channel_args c_args = args.c_channel_args();
201       grpc_resource_quota* client_resource_quota =
202           grpc_resource_quota_from_channel_args(&c_args, true);
203       client_transport_ = grpc_create_chttp2_transport(
204           &c_args, endpoints.client, true,
205           grpc_resource_user_create(client_resource_quota, "client_transport"));
206       grpc_resource_quota_unref(client_resource_quota);
207       GPR_ASSERT(client_transport_);
208       grpc_channel* channel =
209           grpc_channel_create("target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL,
210                               client_transport_, nullptr, 0, nullptr);
211       grpc_chttp2_transport_start_reading(client_transport_, nullptr, nullptr,
212                                           nullptr);
213
214       channel_ = ::grpc::CreateChannelInternal(
215           "", channel,
216           std::vector<std::unique_ptr<
217               experimental::ClientInterceptorFactoryInterface>>());
218     }
219   }
220
221   ~EndpointPairFixture() override {
222     server_->Shutdown();
223     cq_->Shutdown();
224     void* tag;
225     bool ok;
226     while (cq_->Next(&tag, &ok)) {
227     }
228   }
229
230   void AddToLabel(std::ostream& out, benchmark::State& state) override {
231     BaseFixture::AddToLabel(out, state);
232     out << " polls/iter:"
233         << static_cast<double>(grpc_get_cq_poll_num(this->cq()->cq())) /
234                state.iterations();
235   }
236
237   ServerCompletionQueue* cq() { return cq_.get(); }
238   std::shared_ptr<Channel> channel() { return channel_; }
239
240  protected:
241   grpc_endpoint_pair endpoint_pair_;
242   grpc_transport* client_transport_;
243   grpc_transport* server_transport_;
244
245  private:
246   std::unique_ptr<Server> server_;
247   std::unique_ptr<ServerCompletionQueue> cq_;
248   std::shared_ptr<Channel> channel_;
249 };
250
251 class SockPair : public EndpointPairFixture {
252  public:
253   explicit SockPair(Service* service,
254                     const FixtureConfiguration& fixture_configuration =
255                         FixtureConfiguration())
256       : EndpointPairFixture(service,
257                             grpc_iomgr_create_endpoint_pair("test", nullptr),
258                             fixture_configuration) {}
259 };
260
261 /* Use InProcessCHTTP2 instead. This class (with stats as an explicit parameter)
262    is here only to be able to initialize both the base class and stats_ with the
263    same stats instance without accessing the stats_ fields before the object is
264    properly initialized. */
265 class InProcessCHTTP2WithExplicitStats : public EndpointPairFixture {
266  public:
267   InProcessCHTTP2WithExplicitStats(
268       Service* service, grpc_passthru_endpoint_stats* stats,
269       const FixtureConfiguration& fixture_configuration)
270       : EndpointPairFixture(service, MakeEndpoints(stats),
271                             fixture_configuration),
272         stats_(stats) {}
273
274   ~InProcessCHTTP2WithExplicitStats() override {
275     if (stats_ != nullptr) {
276       grpc_passthru_endpoint_stats_destroy(stats_);
277     }
278   }
279
280   void AddToLabel(std::ostream& out, benchmark::State& state) override {
281     EndpointPairFixture::AddToLabel(out, state);
282     out << " writes/iter:"
283         << static_cast<double>(gpr_atm_no_barrier_load(&stats_->num_writes)) /
284                static_cast<double>(state.iterations());
285   }
286
287  private:
288   grpc_passthru_endpoint_stats* stats_;
289
290   static grpc_endpoint_pair MakeEndpoints(grpc_passthru_endpoint_stats* stats) {
291     grpc_endpoint_pair p;
292     grpc_passthru_endpoint_create(&p.client, &p.server, stats);
293     return p;
294   }
295 };
296
297 class InProcessCHTTP2 : public InProcessCHTTP2WithExplicitStats {
298  public:
299   explicit InProcessCHTTP2(Service* service,
300                            const FixtureConfiguration& fixture_configuration =
301                                FixtureConfiguration())
302       : InProcessCHTTP2WithExplicitStats(service,
303                                          grpc_passthru_endpoint_stats_create(),
304                                          fixture_configuration) {}
305 };
306
307 ////////////////////////////////////////////////////////////////////////////////
308 // Minimal stack fixtures
309
310 class MinStackConfiguration : public FixtureConfiguration {
311   void ApplyCommonChannelArguments(ChannelArguments* a) const override {
312     a->SetInt(GRPC_ARG_MINIMAL_STACK, 1);
313     FixtureConfiguration::ApplyCommonChannelArguments(a);
314   }
315
316   void ApplyCommonServerBuilderConfig(ServerBuilder* b) const override {
317     b->AddChannelArgument(GRPC_ARG_MINIMAL_STACK, 1);
318     FixtureConfiguration::ApplyCommonServerBuilderConfig(b);
319   }
320 };
321
322 template <class Base>
323 class MinStackize : public Base {
324  public:
325   explicit MinStackize(Service* service)
326       : Base(service, MinStackConfiguration()) {}
327 };
328
329 typedef MinStackize<TCP> MinTCP;
330 typedef MinStackize<UDS> MinUDS;
331 typedef MinStackize<InProcess> MinInProcess;
332 typedef MinStackize<SockPair> MinSockPair;
333 typedef MinStackize<InProcessCHTTP2> MinInProcessCHTTP2;
334
335 }  // namespace testing
336 }  // namespace grpc
337
338 #endif