fullstack_fixtures.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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. #ifndef TEST_CPP_MICROBENCHMARKS_FULLSTACK_FIXTURES_H
  19. #define TEST_CPP_MICROBENCHMARKS_FULLSTACK_FIXTURES_H
  20. #include <grpc/support/atm.h>
  21. #include <grpc/support/log.h>
  22. #include <grpcpp/channel.h>
  23. #include <grpcpp/create_channel.h>
  24. #include <grpcpp/security/credentials.h>
  25. #include <grpcpp/security/server_credentials.h>
  26. #include <grpcpp/server.h>
  27. #include <grpcpp/server_builder.h>
  28. #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
  29. #include "src/core/lib/channel/channel_args.h"
  30. #include "src/core/lib/iomgr/endpoint.h"
  31. #include "src/core/lib/iomgr/endpoint_pair.h"
  32. #include "src/core/lib/iomgr/exec_ctx.h"
  33. #include "src/core/lib/iomgr/tcp_posix.h"
  34. #include "src/core/lib/surface/channel.h"
  35. #include "src/core/lib/surface/completion_queue.h"
  36. #include "src/core/lib/surface/server.h"
  37. #include "src/cpp/client/create_channel_internal.h"
  38. #include "test/core/util/passthru_endpoint.h"
  39. #include "test/core/util/port.h"
  40. #include "test/cpp/microbenchmarks/helpers.h"
  41. namespace grpc {
  42. namespace testing {
  43. class FixtureConfiguration {
  44. public:
  45. virtual ~FixtureConfiguration() {}
  46. virtual void ApplyCommonChannelArguments(ChannelArguments* c) const {
  47. c->SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, INT_MAX);
  48. c->SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, INT_MAX);
  49. c->SetResourceQuota(ResourceQuota());
  50. }
  51. virtual void ApplyCommonServerBuilderConfig(ServerBuilder* b) const {
  52. b->SetMaxReceiveMessageSize(INT_MAX);
  53. b->SetMaxSendMessageSize(INT_MAX);
  54. }
  55. };
  56. class BaseFixture : public TrackCounters {};
  57. class FullstackFixture : public BaseFixture {
  58. public:
  59. FullstackFixture(Service* service, const FixtureConfiguration& config,
  60. const std::string& address) {
  61. ServerBuilder b;
  62. if (address.length() > 0) {
  63. b.AddListeningPort(address, InsecureServerCredentials());
  64. }
  65. cq_ = b.AddCompletionQueue(true);
  66. b.RegisterService(service);
  67. config.ApplyCommonServerBuilderConfig(&b);
  68. server_ = b.BuildAndStart();
  69. ChannelArguments args;
  70. config.ApplyCommonChannelArguments(&args);
  71. if (address.length() > 0) {
  72. channel_ = grpc::CreateCustomChannel(address,
  73. InsecureChannelCredentials(), args);
  74. } else {
  75. channel_ = server_->InProcessChannel(args);
  76. }
  77. }
  78. ~FullstackFixture() override {
  79. server_->Shutdown();
  80. cq_->Shutdown();
  81. void* tag;
  82. bool ok;
  83. while (cq_->Next(&tag, &ok)) {
  84. }
  85. }
  86. void AddToLabel(std::ostream& out, benchmark::State& state) override {
  87. BaseFixture::AddToLabel(out, state);
  88. out << " polls/iter:"
  89. << static_cast<double>(grpc_get_cq_poll_num(this->cq()->cq())) /
  90. state.iterations();
  91. }
  92. ServerCompletionQueue* cq() { return cq_.get(); }
  93. std::shared_ptr<Channel> channel() { return channel_; }
  94. private:
  95. std::unique_ptr<Server> server_;
  96. std::unique_ptr<ServerCompletionQueue> cq_;
  97. std::shared_ptr<Channel> channel_;
  98. };
  99. class TCP : public FullstackFixture {
  100. public:
  101. explicit TCP(Service* service,
  102. const FixtureConfiguration& fixture_configuration =
  103. FixtureConfiguration())
  104. : FullstackFixture(service, fixture_configuration, MakeAddress(&port_)) {}
  105. ~TCP() override { grpc_recycle_unused_port(port_); }
  106. private:
  107. int port_;
  108. static std::string MakeAddress(int* port) {
  109. *port = grpc_pick_unused_port_or_die();
  110. std::stringstream addr;
  111. addr << "localhost:" << *port;
  112. return addr.str();
  113. }
  114. };
  115. class UDS : public FullstackFixture {
  116. public:
  117. explicit UDS(Service* service,
  118. const FixtureConfiguration& fixture_configuration =
  119. FixtureConfiguration())
  120. : FullstackFixture(service, fixture_configuration, MakeAddress(&port_)) {}
  121. ~UDS() override { grpc_recycle_unused_port(port_); }
  122. private:
  123. int port_;
  124. static std::string MakeAddress(int* port) {
  125. *port = grpc_pick_unused_port_or_die(); // just for a unique id - not a
  126. // real port
  127. std::stringstream addr;
  128. addr << "unix:/tmp/bm_fullstack." << *port;
  129. return addr.str();
  130. }
  131. };
  132. class InProcess : public FullstackFixture {
  133. public:
  134. explicit InProcess(Service* service,
  135. const FixtureConfiguration& fixture_configuration =
  136. FixtureConfiguration())
  137. : FullstackFixture(service, fixture_configuration, "") {}
  138. ~InProcess() override {}
  139. };
  140. class EndpointPairFixture : public BaseFixture {
  141. public:
  142. EndpointPairFixture(Service* service, grpc_endpoint_pair endpoints,
  143. const FixtureConfiguration& fixture_configuration)
  144. : endpoint_pair_(endpoints) {
  145. ServerBuilder b;
  146. cq_ = b.AddCompletionQueue(true);
  147. b.RegisterService(service);
  148. fixture_configuration.ApplyCommonServerBuilderConfig(&b);
  149. server_ = b.BuildAndStart();
  150. grpc_core::ExecCtx exec_ctx;
  151. /* add server endpoint to server_
  152. * */
  153. {
  154. grpc_core::Server* core_server =
  155. grpc_core::Server::FromC(server_->c_server());
  156. const grpc_channel_args* server_args = core_server->channel_args();
  157. server_transport_ = grpc_create_chttp2_transport(
  158. server_args, endpoints.server, false /* is_client */);
  159. for (grpc_pollset* pollset : core_server->pollsets()) {
  160. grpc_endpoint_add_to_pollset(endpoints.server, pollset);
  161. }
  162. GPR_ASSERT(GRPC_LOG_IF_ERROR(
  163. "SetupTransport",
  164. core_server->SetupTransport(server_transport_, nullptr, server_args,
  165. nullptr)));
  166. grpc_chttp2_transport_start_reading(server_transport_, nullptr, nullptr,
  167. nullptr);
  168. }
  169. /* create channel */
  170. {
  171. ChannelArguments args;
  172. args.SetString(GRPC_ARG_DEFAULT_AUTHORITY, "test.authority");
  173. fixture_configuration.ApplyCommonChannelArguments(&args);
  174. grpc_channel_args c_args = args.c_channel_args();
  175. client_transport_ =
  176. grpc_create_chttp2_transport(&c_args, endpoints.client, true);
  177. GPR_ASSERT(client_transport_);
  178. grpc_channel* channel = grpc_channel_create_internal(
  179. "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, client_transport_,
  180. nullptr);
  181. grpc_chttp2_transport_start_reading(client_transport_, nullptr, nullptr,
  182. nullptr);
  183. channel_ = grpc::CreateChannelInternal(
  184. "", channel,
  185. std::vector<std::unique_ptr<
  186. experimental::ClientInterceptorFactoryInterface>>());
  187. }
  188. }
  189. ~EndpointPairFixture() override {
  190. server_->Shutdown();
  191. cq_->Shutdown();
  192. void* tag;
  193. bool ok;
  194. while (cq_->Next(&tag, &ok)) {
  195. }
  196. }
  197. void AddToLabel(std::ostream& out, benchmark::State& state) override {
  198. BaseFixture::AddToLabel(out, state);
  199. out << " polls/iter:"
  200. << static_cast<double>(grpc_get_cq_poll_num(this->cq()->cq())) /
  201. state.iterations();
  202. }
  203. ServerCompletionQueue* cq() { return cq_.get(); }
  204. std::shared_ptr<Channel> channel() { return channel_; }
  205. protected:
  206. grpc_endpoint_pair endpoint_pair_;
  207. grpc_transport* client_transport_;
  208. grpc_transport* server_transport_;
  209. private:
  210. std::unique_ptr<Server> server_;
  211. std::unique_ptr<ServerCompletionQueue> cq_;
  212. std::shared_ptr<Channel> channel_;
  213. };
  214. class SockPair : public EndpointPairFixture {
  215. public:
  216. explicit SockPair(Service* service,
  217. const FixtureConfiguration& fixture_configuration =
  218. FixtureConfiguration())
  219. : EndpointPairFixture(service,
  220. grpc_iomgr_create_endpoint_pair("test", nullptr),
  221. fixture_configuration) {}
  222. };
  223. /* Use InProcessCHTTP2 instead. This class (with stats as an explicit parameter)
  224. is here only to be able to initialize both the base class and stats_ with the
  225. same stats instance without accessing the stats_ fields before the object is
  226. properly initialized. */
  227. class InProcessCHTTP2WithExplicitStats : public EndpointPairFixture {
  228. public:
  229. InProcessCHTTP2WithExplicitStats(
  230. Service* service, grpc_passthru_endpoint_stats* stats,
  231. const FixtureConfiguration& fixture_configuration)
  232. : EndpointPairFixture(service, MakeEndpoints(stats),
  233. fixture_configuration),
  234. stats_(stats) {}
  235. ~InProcessCHTTP2WithExplicitStats() override {
  236. if (stats_ != nullptr) {
  237. grpc_passthru_endpoint_stats_destroy(stats_);
  238. }
  239. }
  240. void AddToLabel(std::ostream& out, benchmark::State& state) override {
  241. EndpointPairFixture::AddToLabel(out, state);
  242. out << " writes/iter:"
  243. << static_cast<double>(gpr_atm_no_barrier_load(&stats_->num_writes)) /
  244. static_cast<double>(state.iterations());
  245. }
  246. private:
  247. grpc_passthru_endpoint_stats* stats_;
  248. static grpc_endpoint_pair MakeEndpoints(grpc_passthru_endpoint_stats* stats) {
  249. grpc_endpoint_pair p;
  250. grpc_passthru_endpoint_create(&p.client, &p.server, stats);
  251. return p;
  252. }
  253. };
  254. class InProcessCHTTP2 : public InProcessCHTTP2WithExplicitStats {
  255. public:
  256. explicit InProcessCHTTP2(Service* service,
  257. const FixtureConfiguration& fixture_configuration =
  258. FixtureConfiguration())
  259. : InProcessCHTTP2WithExplicitStats(service,
  260. grpc_passthru_endpoint_stats_create(),
  261. fixture_configuration) {}
  262. };
  263. ////////////////////////////////////////////////////////////////////////////////
  264. // Minimal stack fixtures
  265. class MinStackConfiguration : public FixtureConfiguration {
  266. void ApplyCommonChannelArguments(ChannelArguments* a) const override {
  267. a->SetInt(GRPC_ARG_MINIMAL_STACK, 1);
  268. FixtureConfiguration::ApplyCommonChannelArguments(a);
  269. }
  270. void ApplyCommonServerBuilderConfig(ServerBuilder* b) const override {
  271. b->AddChannelArgument(GRPC_ARG_MINIMAL_STACK, 1);
  272. FixtureConfiguration::ApplyCommonServerBuilderConfig(b);
  273. }
  274. };
  275. template <class Base>
  276. class MinStackize : public Base {
  277. public:
  278. explicit MinStackize(Service* service)
  279. : Base(service, MinStackConfiguration()) {}
  280. };
  281. typedef MinStackize<TCP> MinTCP;
  282. typedef MinStackize<UDS> MinUDS;
  283. typedef MinStackize<InProcess> MinInProcess;
  284. typedef MinStackize<SockPair> MinSockPair;
  285. typedef MinStackize<InProcessCHTTP2> MinInProcessCHTTP2;
  286. } // namespace testing
  287. } // namespace grpc
  288. #endif