qps_worker.cc 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. *
  3. * Copyright 2015 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. #include "test/cpp/qps/qps_worker.h"
  19. #include <memory>
  20. #include <mutex>
  21. #include <sstream>
  22. #include <string>
  23. #include <thread>
  24. #include <vector>
  25. #include "absl/memory/memory.h"
  26. #include <grpc/grpc.h>
  27. #include <grpc/support/alloc.h>
  28. #include <grpc/support/cpu.h>
  29. #include <grpc/support/log.h>
  30. #include <grpcpp/client_context.h>
  31. #include <grpcpp/security/server_credentials.h>
  32. #include <grpcpp/server.h>
  33. #include <grpcpp/server_builder.h>
  34. #include "src/core/lib/gprpp/host_port.h"
  35. #include "src/proto/grpc/testing/worker_service.grpc.pb.h"
  36. #include "test/core/util/grpc_profiler.h"
  37. #include "test/core/util/histogram.h"
  38. #include "test/cpp/qps/client.h"
  39. #include "test/cpp/qps/qps_server_builder.h"
  40. #include "test/cpp/qps/server.h"
  41. #include "test/cpp/util/create_test_channel.h"
  42. #include "test/cpp/util/test_credentials_provider.h"
  43. namespace grpc {
  44. namespace testing {
  45. static std::unique_ptr<Client> CreateClient(const ClientConfig& config) {
  46. gpr_log(GPR_INFO, "Starting client of type %s %s %d",
  47. ClientType_Name(config.client_type()).c_str(),
  48. RpcType_Name(config.rpc_type()).c_str(),
  49. config.payload_config().has_bytebuf_params());
  50. switch (config.client_type()) {
  51. case ClientType::SYNC_CLIENT:
  52. return CreateSynchronousClient(config);
  53. case ClientType::ASYNC_CLIENT:
  54. return config.payload_config().has_bytebuf_params()
  55. ? CreateGenericAsyncStreamingClient(config)
  56. : CreateAsyncClient(config);
  57. case ClientType::CALLBACK_CLIENT:
  58. return CreateCallbackClient(config);
  59. default:
  60. abort();
  61. }
  62. }
  63. static std::unique_ptr<Server> CreateServer(const ServerConfig& config) {
  64. gpr_log(GPR_INFO, "Starting server of type %s",
  65. ServerType_Name(config.server_type()).c_str());
  66. switch (config.server_type()) {
  67. case ServerType::SYNC_SERVER:
  68. return CreateSynchronousServer(config);
  69. case ServerType::ASYNC_SERVER:
  70. return CreateAsyncServer(config);
  71. case ServerType::ASYNC_GENERIC_SERVER:
  72. return CreateAsyncGenericServer(config);
  73. case ServerType::CALLBACK_SERVER:
  74. return CreateCallbackServer(config);
  75. default:
  76. abort();
  77. }
  78. }
  79. class ScopedProfile final {
  80. public:
  81. ScopedProfile(const char* filename, bool enable) : enable_(enable) {
  82. if (enable_) grpc_profiler_start(filename);
  83. }
  84. ~ScopedProfile() {
  85. if (enable_) grpc_profiler_stop();
  86. }
  87. private:
  88. const bool enable_;
  89. };
  90. class WorkerServiceImpl final : public WorkerService::Service {
  91. public:
  92. WorkerServiceImpl(int server_port, QpsWorker* worker)
  93. : acquired_(false), server_port_(server_port), worker_(worker) {}
  94. Status RunClient(
  95. ServerContext* ctx,
  96. ServerReaderWriter<ClientStatus, ClientArgs>* stream) override {
  97. gpr_log(GPR_INFO, "RunClient: Entering");
  98. InstanceGuard g(this);
  99. if (!g.Acquired()) {
  100. return Status(StatusCode::RESOURCE_EXHAUSTED, "Client worker busy");
  101. }
  102. ScopedProfile profile("qps_client.prof", false);
  103. Status ret = RunClientBody(ctx, stream);
  104. gpr_log(GPR_INFO, "RunClient: Returning");
  105. return ret;
  106. }
  107. Status RunServer(
  108. ServerContext* ctx,
  109. ServerReaderWriter<ServerStatus, ServerArgs>* stream) override {
  110. gpr_log(GPR_INFO, "RunServer: Entering");
  111. InstanceGuard g(this);
  112. if (!g.Acquired()) {
  113. return Status(StatusCode::RESOURCE_EXHAUSTED, "Server worker busy");
  114. }
  115. ScopedProfile profile("qps_server.prof", false);
  116. Status ret = RunServerBody(ctx, stream);
  117. gpr_log(GPR_INFO, "RunServer: Returning");
  118. return ret;
  119. }
  120. Status CoreCount(ServerContext* /*ctx*/, const CoreRequest*,
  121. CoreResponse* resp) override {
  122. resp->set_cores(gpr_cpu_num_cores());
  123. return Status::OK;
  124. }
  125. Status QuitWorker(ServerContext* /*ctx*/, const Void*, Void*) override {
  126. InstanceGuard g(this);
  127. if (!g.Acquired()) {
  128. return Status(StatusCode::RESOURCE_EXHAUSTED, "Quitting worker busy");
  129. }
  130. worker_->MarkDone();
  131. return Status::OK;
  132. }
  133. private:
  134. // Protect against multiple clients using this worker at once.
  135. class InstanceGuard {
  136. public:
  137. explicit InstanceGuard(WorkerServiceImpl* impl)
  138. : impl_(impl), acquired_(impl->TryAcquireInstance()) {}
  139. ~InstanceGuard() {
  140. if (acquired_) {
  141. impl_->ReleaseInstance();
  142. }
  143. }
  144. bool Acquired() const { return acquired_; }
  145. private:
  146. WorkerServiceImpl* const impl_;
  147. const bool acquired_;
  148. };
  149. bool TryAcquireInstance() {
  150. std::lock_guard<std::mutex> g(mu_);
  151. if (acquired_) return false;
  152. acquired_ = true;
  153. return true;
  154. }
  155. void ReleaseInstance() {
  156. std::lock_guard<std::mutex> g(mu_);
  157. GPR_ASSERT(acquired_);
  158. acquired_ = false;
  159. }
  160. Status RunClientBody(ServerContext* /*ctx*/,
  161. ServerReaderWriter<ClientStatus, ClientArgs>* stream) {
  162. ClientArgs args;
  163. if (!stream->Read(&args)) {
  164. return Status(StatusCode::INVALID_ARGUMENT, "Couldn't read args");
  165. }
  166. if (!args.has_setup()) {
  167. return Status(StatusCode::INVALID_ARGUMENT, "Invalid setup arg");
  168. }
  169. gpr_log(GPR_INFO, "RunClientBody: about to create client");
  170. std::unique_ptr<Client> client = CreateClient(args.setup());
  171. if (!client) {
  172. return Status(StatusCode::INVALID_ARGUMENT, "Couldn't create client");
  173. }
  174. gpr_log(GPR_INFO, "RunClientBody: client created");
  175. ClientStatus status;
  176. if (!stream->Write(status)) {
  177. return Status(StatusCode::UNKNOWN, "Client couldn't report init status");
  178. }
  179. gpr_log(GPR_INFO, "RunClientBody: creation status reported");
  180. while (stream->Read(&args)) {
  181. gpr_log(GPR_INFO, "RunClientBody: Message read");
  182. if (!args.has_mark()) {
  183. gpr_log(GPR_INFO, "RunClientBody: Message is not a mark!");
  184. return Status(StatusCode::INVALID_ARGUMENT, "Invalid mark");
  185. }
  186. *status.mutable_stats() = client->Mark(args.mark().reset());
  187. if (!stream->Write(status)) {
  188. return Status(StatusCode::UNKNOWN, "Client couldn't respond to mark");
  189. }
  190. gpr_log(GPR_INFO, "RunClientBody: Mark response given");
  191. }
  192. gpr_log(GPR_INFO, "RunClientBody: Awaiting Threads Completion");
  193. client->AwaitThreadsCompletion();
  194. gpr_log(GPR_INFO, "RunClientBody: Returning");
  195. return Status::OK;
  196. }
  197. Status RunServerBody(ServerContext* /*ctx*/,
  198. ServerReaderWriter<ServerStatus, ServerArgs>* stream) {
  199. ServerArgs args;
  200. if (!stream->Read(&args)) {
  201. return Status(StatusCode::INVALID_ARGUMENT, "Couldn't read server args");
  202. }
  203. if (!args.has_setup()) {
  204. return Status(StatusCode::INVALID_ARGUMENT, "Bad server creation args");
  205. }
  206. if (server_port_ > 0 && args.setup().port() == 0) {
  207. args.mutable_setup()->set_port(server_port_);
  208. }
  209. gpr_log(GPR_INFO, "RunServerBody: about to create server");
  210. std::unique_ptr<Server> server = CreateServer(args.setup());
  211. if (g_inproc_servers != nullptr) {
  212. g_inproc_servers->push_back(server.get());
  213. }
  214. if (!server) {
  215. return Status(StatusCode::INVALID_ARGUMENT, "Couldn't create server");
  216. }
  217. gpr_log(GPR_INFO, "RunServerBody: server created");
  218. ServerStatus status;
  219. status.set_port(server->port());
  220. status.set_cores(server->cores());
  221. if (!stream->Write(status)) {
  222. return Status(StatusCode::UNKNOWN, "Server couldn't report init status");
  223. }
  224. gpr_log(GPR_INFO, "RunServerBody: creation status reported");
  225. while (stream->Read(&args)) {
  226. gpr_log(GPR_INFO, "RunServerBody: Message read");
  227. if (!args.has_mark()) {
  228. gpr_log(GPR_INFO, "RunServerBody: Message not a mark!");
  229. return Status(StatusCode::INVALID_ARGUMENT, "Invalid mark");
  230. }
  231. *status.mutable_stats() = server->Mark(args.mark().reset());
  232. if (!stream->Write(status)) {
  233. return Status(StatusCode::UNKNOWN, "Server couldn't respond to mark");
  234. }
  235. gpr_log(GPR_INFO, "RunServerBody: Mark response given");
  236. }
  237. gpr_log(GPR_INFO, "RunServerBody: Returning");
  238. return Status::OK;
  239. }
  240. std::mutex mu_;
  241. bool acquired_;
  242. int server_port_;
  243. QpsWorker* worker_;
  244. };
  245. QpsWorker::QpsWorker(int driver_port, int server_port,
  246. const std::string& credential_type) {
  247. impl_ = absl::make_unique<WorkerServiceImpl>(server_port, this);
  248. gpr_atm_rel_store(&done_, static_cast<gpr_atm>(0));
  249. std::unique_ptr<ServerBuilder> builder = CreateQpsServerBuilder();
  250. builder->AddChannelArgument(GRPC_ARG_ALLOW_REUSEPORT, 0);
  251. if (driver_port >= 0) {
  252. std::string server_address = grpc_core::JoinHostPort("::", driver_port);
  253. builder->AddListeningPort(
  254. server_address.c_str(),
  255. GetCredentialsProvider()->GetServerCredentials(credential_type));
  256. }
  257. builder->RegisterService(impl_.get());
  258. server_ = builder->BuildAndStart();
  259. if (server_ == nullptr) {
  260. gpr_log(GPR_ERROR,
  261. "QpsWorker: Fail to BuildAndStart(driver_port=%d, server_port=%d)",
  262. driver_port, server_port);
  263. } else {
  264. gpr_log(GPR_INFO,
  265. "QpsWorker: BuildAndStart(driver_port=%d, server_port=%d) done",
  266. driver_port, server_port);
  267. }
  268. }
  269. QpsWorker::~QpsWorker() {}
  270. bool QpsWorker::Done() const {
  271. return (gpr_atm_acq_load(&done_) != static_cast<gpr_atm>(0));
  272. }
  273. void QpsWorker::MarkDone() {
  274. gpr_atm_rel_store(&done_, static_cast<gpr_atm>(1));
  275. }
  276. } // namespace testing
  277. } // namespace grpc