blob: 2583ceb8192693ee253a639f3b856ac8b827290d [file] [log] [blame]
Craig Tillere4860192015-02-23 17:10:41 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Craig Tillere4860192015-02-23 17:10:41 -08004 * 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
Vijay Paid02dd302016-01-27 11:23:34 -080034#include <deque>
Craig Tiller2d0f36c2015-02-23 23:16:17 -080035#include <list>
36#include <thread>
Vijay Pai7d45cdb2016-02-01 13:00:19 -080037#include <unordered_map>
Craig Tiller2d0f36c2015-02-23 23:16:17 -080038#include <vector>
yang-g9e2f90c2015-08-21 15:35:03 -070039
David Garcia Quintas6a484052016-01-25 19:12:37 -080040#include <grpc++/channel.h>
yang-g9e2f90c2015-08-21 15:35:03 -070041#include <grpc++/client_context.h>
42#include <grpc++/create_channel.h>
Vijay Paid02dd302016-01-27 11:23:34 -080043#include <grpc/support/alloc.h>
44#include <grpc/support/host_port.h>
45#include <grpc/support/log.h>
vjpai63326282016-03-14 17:12:52 -070046#include <gtest/gtest.h>
yang-g9e2f90c2015-08-21 15:35:03 -070047
Craig Tiller9533d042016-03-25 17:11:06 -070048#include "src/core/lib/support/env.h"
Vijay Paid02dd302016-01-27 11:23:34 -080049#include "src/proto/grpc/testing/services.grpc.pb.h"
Craig Tillere9a6eb72015-04-09 15:51:41 -070050#include "test/core/util/port.h"
Craig Tiller882431f2015-05-19 09:25:37 -070051#include "test/core/util/test_config.h"
yang-g9e2f90c2015-08-21 15:35:03 -070052#include "test/cpp/qps/driver.h"
53#include "test/cpp/qps/histogram.h"
54#include "test/cpp/qps/qps_worker.h"
Jan Tattermusch33c161d2016-04-15 14:45:49 -070055#include "test/cpp/qps/stats.h"
Craig Tillere4860192015-02-23 17:10:41 -080056
Craig Tiller2d0f36c2015-02-23 23:16:17 -080057using std::list;
58using std::thread;
59using std::unique_ptr;
Craig Tillere9a6eb72015-04-09 15:51:41 -070060using std::deque;
Craig Tiller4ef7a292015-02-23 17:29:01 -080061using std::vector;
Craig Tiller4ef7a292015-02-23 17:29:01 -080062
Craig Tiller6af9ed02015-03-02 22:42:10 -080063namespace grpc {
64namespace testing {
Vijay Pai59567422016-02-01 13:28:55 -080065static std::string get_host(const std::string& worker) {
66 char* host;
67 char* port;
Vijay Pai7d45cdb2016-02-01 13:00:19 -080068
69 gpr_split_host_port(worker.c_str(), &host, &port);
Vijay Pai33e51182016-02-01 16:40:06 -080070 const string s(host);
Vijay Pai7d45cdb2016-02-01 13:00:19 -080071
72 gpr_free(host);
73 gpr_free(port);
74 return s;
75}
76
Vijay Pai59567422016-02-01 13:28:55 -080077static std::unordered_map<string, std::deque<int>> get_hosts_and_cores(
78 const deque<string>& workers) {
79 std::unordered_map<string, std::deque<int>> hosts;
Vijay Pai7d45cdb2016-02-01 13:00:19 -080080 for (auto it = workers.begin(); it != workers.end(); it++) {
Vijay Pai33e51182016-02-01 16:40:06 -080081 const string host = get_host(*it);
Vijay Pai7d45cdb2016-02-01 13:00:19 -080082 if (hosts.find(host) == hosts.end()) {
83 auto stub = WorkerService::NewStub(
84 CreateChannel(*it, InsecureChannelCredentials()));
85 grpc::ClientContext ctx;
86 CoreRequest dummy;
87 CoreResponse cores;
88 grpc::Status s = stub->CoreCount(&ctx, dummy, &cores);
89 assert(s.ok());
90 std::deque<int> dq;
Vijay Pai59567422016-02-01 13:28:55 -080091 for (int i = 0; i < cores.cores(); i++) {
Vijay Pai7d45cdb2016-02-01 13:00:19 -080092 dq.push_back(i);
93 }
94 hosts[host] = dq;
95 }
96 }
97 return hosts;
98}
99
100static deque<string> get_workers(const string& name) {
Craig Tiller4ef7a292015-02-23 17:29:01 -0800101 char* env = gpr_getenv(name.c_str());
Craig Tillere9a6eb72015-04-09 15:51:41 -0700102 if (!env) return deque<string>();
Craig Tiller4ef7a292015-02-23 17:29:01 -0800103
Craig Tillere9a6eb72015-04-09 15:51:41 -0700104 deque<string> out;
Craig Tiller4ef7a292015-02-23 17:29:01 -0800105 char* p = env;
106 for (;;) {
Craig Tiller6af9ed02015-03-02 22:42:10 -0800107 char* comma = strchr(p, ',');
108 if (comma) {
109 out.emplace_back(p, comma);
110 p = comma + 1;
111 } else {
112 out.emplace_back(p);
113 gpr_free(env);
114 return out;
115 }
Craig Tiller4ef7a292015-02-23 17:29:01 -0800116 }
117}
118
Jan Tattermusch33c161d2016-04-15 14:45:49 -0700119// helpers for postprocess_scenario_result
120static double WallTime(ClientStats s) { return s.time_elapsed(); }
121static double SystemTime(ClientStats s) { return s.time_system(); }
122static double UserTime(ClientStats s) { return s.time_user(); }
123static double ServerWallTime(ServerStats s) { return s.time_elapsed(); }
124static double ServerSystemTime(ServerStats s) { return s.time_system(); }
125static double ServerUserTime(ServerStats s) { return s.time_user(); }
126static int Cores(int n) { return n; }
127
128// Postprocess ScenarioResult and populate result summary.
129static void postprocess_scenario_result(ScenarioResult* result) {
130 Histogram histogram;
131 histogram.MergeProto(result->latencies());
132
133 auto qps = histogram.Count() / average(result->client_stats(), WallTime);
134 auto qps_per_server_core = qps / sum(result->server_cores(), Cores);
135
136 result->mutable_summary()->set_qps(qps);
137 result->mutable_summary()->set_qps_per_server_core(qps_per_server_core);
138 result->mutable_summary()->set_latency_50(histogram.Percentile(50));
139 result->mutable_summary()->set_latency_90(histogram.Percentile(90));
140 result->mutable_summary()->set_latency_95(histogram.Percentile(95));
141 result->mutable_summary()->set_latency_99(histogram.Percentile(99));
142 result->mutable_summary()->set_latency_999(histogram.Percentile(99.9));
143
Jan Tattermusche9a8d892016-04-15 15:38:17 -0700144 auto server_system_time = 100.0 *
145 sum(result->server_stats(), ServerSystemTime) /
146 sum(result->server_stats(), ServerWallTime);
Jan Tattermusch33c161d2016-04-15 14:45:49 -0700147 auto server_user_time = 100.0 * sum(result->server_stats(), ServerUserTime) /
Jan Tattermusche9a8d892016-04-15 15:38:17 -0700148 sum(result->server_stats(), ServerWallTime);
Jan Tattermusch33c161d2016-04-15 14:45:49 -0700149 auto client_system_time = 100.0 * sum(result->client_stats(), SystemTime) /
Jan Tattermusche9a8d892016-04-15 15:38:17 -0700150 sum(result->client_stats(), WallTime);
Jan Tattermusch33c161d2016-04-15 14:45:49 -0700151 auto client_user_time = 100.0 * sum(result->client_stats(), UserTime) /
Jan Tattermusche9a8d892016-04-15 15:38:17 -0700152 sum(result->client_stats(), WallTime);
Jan Tattermusch33c161d2016-04-15 14:45:49 -0700153
154 result->mutable_summary()->set_server_system_time(server_system_time);
155 result->mutable_summary()->set_server_user_time(server_user_time);
156 result->mutable_summary()->set_client_system_time(client_system_time);
157 result->mutable_summary()->set_client_user_time(client_user_time);
158}
159
Vijay Pai4d06e2e2015-07-31 10:20:42 -0700160// Namespace for classes and functions used only in RunScenario
161// Using this rather than local definitions to workaround gcc-4.4 limitations
Vijay Pai90e73692015-08-05 19:15:36 -0700162// regarding using templates without linkage
Vijay Pai4d06e2e2015-07-31 10:20:42 -0700163namespace runsc {
164
165// ClientContext allocator
vjpai63326282016-03-14 17:12:52 -0700166static ClientContext* AllocContext(list<ClientContext>* contexts) {
Vijay Pai4d06e2e2015-07-31 10:20:42 -0700167 contexts->emplace_back();
Craig Tillerb17b7f42015-10-07 08:48:51 -0700168 auto context = &contexts->back();
Craig Tillerb17b7f42015-10-07 08:48:51 -0700169 return context;
Vijay Pai4d06e2e2015-07-31 10:20:42 -0700170}
171
172struct ServerData {
vjpai119c1032015-10-29 01:21:04 -0700173 unique_ptr<WorkerService::Stub> stub;
Vijay Pai4d06e2e2015-07-31 10:20:42 -0700174 unique_ptr<ClientReaderWriter<ServerArgs, ServerStatus>> stream;
175};
176
177struct ClientData {
vjpai119c1032015-10-29 01:21:04 -0700178 unique_ptr<WorkerService::Stub> stub;
Vijay Pai4d06e2e2015-07-31 10:20:42 -0700179 unique_ptr<ClientReaderWriter<ClientArgs, ClientStatus>> stream;
180};
Vijay Pai3ae11042015-08-11 22:43:14 -0700181} // namespace runsc
Vijay Pai4d06e2e2015-07-31 10:20:42 -0700182
David Garcia Quintas08116502015-05-20 17:27:23 -0700183std::unique_ptr<ScenarioResult> RunScenario(
184 const ClientConfig& initial_client_config, size_t num_clients,
Vijay Pai59567422016-02-01 13:28:55 -0800185 const ServerConfig& initial_server_config, size_t num_servers,
186 int warmup_seconds, int benchmark_seconds, int spawn_local_worker_count) {
Vijay Pai4d06e2e2015-07-31 10:20:42 -0700187 // ClientContext allocations (all are destroyed at scope exit)
Craig Tiller2d0f36c2015-02-23 23:16:17 -0800188 list<ClientContext> contexts;
Craig Tiller2d0f36c2015-02-23 23:16:17 -0800189
David Garcia Quintas6ba29ba2015-05-19 18:29:35 -0700190 // To be added to the result, containing the final configuration used for
Jan Tattermuschc5ebbd52015-11-18 16:50:47 -0800191 // client and config (including host, etc.)
David Garcia Quintas6ba29ba2015-05-19 18:29:35 -0700192 ClientConfig result_client_config;
Vijay Pai33e51182016-02-01 16:40:06 -0800193 const ServerConfig result_server_config = initial_server_config;
David Garcia Quintas6ba29ba2015-05-19 18:29:35 -0700194
Craig Tiller2d0f36c2015-02-23 23:16:17 -0800195 // Get client, server lists
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800196 auto workers = get_workers("QPS_WORKERS");
Craig Tiller6af9ed02015-03-02 22:42:10 -0800197 ClientConfig client_config = initial_client_config;
Craig Tiller4ef7a292015-02-23 17:29:01 -0800198
Craig Tillere9a6eb72015-04-09 15:51:41 -0700199 // Spawn some local workers if desired
200 vector<unique_ptr<QpsWorker>> local_workers;
201 for (int i = 0; i < abs(spawn_local_worker_count); i++) {
Craig Tiller49c3b012015-05-19 08:18:02 -0700202 // act as if we're a new test -- gets a good rng seed
203 static bool called_init = false;
204 if (!called_init) {
Craig Tiller882431f2015-05-19 09:25:37 -0700205 char args_buf[100];
206 strcpy(args_buf, "some-benchmark");
Craig Tiller5c8737d2015-05-21 11:42:17 -0700207 char* args[] = {args_buf};
Craig Tiller49c3b012015-05-19 08:18:02 -0700208 grpc_test_init(1, args);
209 called_init = true;
210 }
211
Craig Tillere9a6eb72015-04-09 15:51:41 -0700212 int driver_port = grpc_pick_unused_port_or_die();
vjpai72a63322015-10-29 02:23:11 -0700213 local_workers.emplace_back(new QpsWorker(driver_port));
Craig Tillere9a6eb72015-04-09 15:51:41 -0700214 char addr[256];
215 sprintf(addr, "localhost:%d", driver_port);
216 if (spawn_local_worker_count < 0) {
217 workers.push_front(addr);
218 } else {
219 workers.push_back(addr);
220 }
221 }
222
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800223 // Setup the hosts and core counts
224 auto hosts_cores = get_hosts_and_cores(workers);
225
Vijay Paid02dd302016-01-27 11:23:34 -0800226 // if num_clients is set to <=0, do dynamic sizing: all workers
227 // except for servers are clients
228 if (num_clients <= 0) {
229 num_clients = workers.size() - num_servers;
230 }
231
Craig Tiller10923c22015-03-03 14:24:49 -0800232 // TODO(ctiller): support running multiple configurations, and binpack
233 // client/server pairs
Craig Tiller6af9ed02015-03-02 22:42:10 -0800234 // to available workers
235 GPR_ASSERT(workers.size() >= num_clients + num_servers);
Craig Tiller2d0f36c2015-02-23 23:16:17 -0800236
237 // Trim to just what we need
Craig Tiller6af9ed02015-03-02 22:42:10 -0800238 workers.resize(num_clients + num_servers);
Craig Tiller2d0f36c2015-02-23 23:16:17 -0800239
240 // Start servers
Vijay Pai4d06e2e2015-07-31 10:20:42 -0700241 using runsc::ServerData;
Vijay Pai90e73692015-08-05 19:15:36 -0700242 // servers is array rather than std::vector to avoid gcc-4.4 issues
243 // where class contained in std::vector must have a copy constructor
vjpaib1db8692015-08-11 22:41:02 -0700244 auto* servers = new ServerData[num_servers];
Craig Tiller6af9ed02015-03-02 22:42:10 -0800245 for (size_t i = 0; i < num_servers; i++) {
vjpai94aada92016-01-26 18:12:30 -0800246 gpr_log(GPR_INFO, "Starting server on %s (worker #%d)", workers[i].c_str(),
vjpai0c31b602016-01-27 09:03:18 -0800247 i);
Julien Boeuf6049ebd2015-11-17 16:53:52 -0800248 servers[i].stub = WorkerService::NewStub(
Julien Boeufe5adc0e2015-10-12 14:08:10 -0700249 CreateChannel(workers[i], InsecureChannelCredentials()));
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800250
251 ServerConfig server_config = initial_server_config;
252 char* host;
253 char* driver_port;
254 char* cli_target;
255 gpr_split_host_port(workers[i].c_str(), &host, &driver_port);
256 string host_str(host);
257 int server_core_limit = initial_server_config.core_limit();
258 int client_core_limit = initial_client_config.core_limit();
259
260 if (server_core_limit == 0 && client_core_limit > 0) {
261 // In this case, limit the server cores if it matches the
262 // same host as one or more clients
Vijay Pai33e51182016-02-01 16:40:06 -0800263 const auto& dq = hosts_cores.at(host_str);
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800264 bool match = false;
265 int limit = dq.size();
266 for (size_t cli = 0; cli < num_clients; cli++) {
Vijay Pai59567422016-02-01 13:28:55 -0800267 if (host_str == get_host(workers[cli + num_servers])) {
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800268 limit -= client_core_limit;
269 match = true;
270 }
271 }
272 if (match) {
273 GPR_ASSERT(limit > 0);
274 server_core_limit = limit;
275 }
276 }
277 if (server_core_limit > 0) {
Vijay Pai33e51182016-02-01 16:40:06 -0800278 auto& dq = hosts_cores.at(host_str);
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800279 GPR_ASSERT(dq.size() >= static_cast<size_t>(server_core_limit));
Vijay Pai59567422016-02-01 13:28:55 -0800280 for (int core = 0; core < server_core_limit; core++) {
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800281 server_config.add_core_list(dq.front());
282 dq.pop_front();
283 }
284 }
285
Craig Tiller6af9ed02015-03-02 22:42:10 -0800286 ServerArgs args;
287 *args.mutable_setup() = server_config;
Vijay Pai90e73692015-08-05 19:15:36 -0700288 servers[i].stream =
vjpai63326282016-03-14 17:12:52 -0700289 servers[i].stub->RunServer(runsc::AllocContext(&contexts));
Vijay Paieed63fa2015-08-05 23:08:34 +0000290 GPR_ASSERT(servers[i].stream->Write(args));
Craig Tiller6af9ed02015-03-02 22:42:10 -0800291 ServerStatus init_status;
Vijay Paieed63fa2015-08-05 23:08:34 +0000292 GPR_ASSERT(servers[i].stream->Read(&init_status));
Craig Tiller6af9ed02015-03-02 22:42:10 -0800293 gpr_join_host_port(&cli_target, host, init_status.port());
294 client_config.add_server_targets(cli_target);
295 gpr_free(host);
296 gpr_free(driver_port);
297 gpr_free(cli_target);
Craig Tiller2d0f36c2015-02-23 23:16:17 -0800298 }
299
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800300 // Targets are all set by now
301 result_client_config = client_config;
Craig Tiller2d0f36c2015-02-23 23:16:17 -0800302 // Start clients
Vijay Pai4d06e2e2015-07-31 10:20:42 -0700303 using runsc::ClientData;
Vijay Pai90e73692015-08-05 19:15:36 -0700304 // clients is array rather than std::vector to avoid gcc-4.4 issues
305 // where class contained in std::vector must have a copy constructor
vjpaib1db8692015-08-11 22:41:02 -0700306 auto* clients = new ClientData[num_clients];
Craig Tiller6af9ed02015-03-02 22:42:10 -0800307 for (size_t i = 0; i < num_clients; i++) {
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800308 const auto& worker = workers[i + num_servers];
Vijay Pai59567422016-02-01 13:28:55 -0800309 gpr_log(GPR_INFO, "Starting client on %s (worker #%d)", worker.c_str(),
310 i + num_servers);
Julien Boeuf6049ebd2015-11-17 16:53:52 -0800311 clients[i].stub = WorkerService::NewStub(
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800312 CreateChannel(worker, InsecureChannelCredentials()));
313 ClientConfig per_client_config = client_config;
314
315 int server_core_limit = initial_server_config.core_limit();
316 int client_core_limit = initial_client_config.core_limit();
317 if ((server_core_limit > 0) || (client_core_limit > 0)) {
Vijay Paidaadcc82016-02-01 16:49:55 -0800318 auto& dq = hosts_cores.at(get_host(worker));
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800319 if (client_core_limit == 0) {
320 // limit client cores if it matches a server host
321 bool match = false;
322 int limit = dq.size();
323 for (size_t srv = 0; srv < num_servers; srv++) {
324 if (get_host(worker) == get_host(workers[srv])) {
325 match = true;
326 }
327 }
328 if (match) {
Vijay Pai6b056392016-02-01 13:01:34 -0800329 GPR_ASSERT(limit > 0);
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800330 client_core_limit = limit;
331 }
332 }
333 if (client_core_limit > 0) {
334 GPR_ASSERT(dq.size() >= static_cast<size_t>(client_core_limit));
Vijay Pai59567422016-02-01 13:28:55 -0800335 for (int core = 0; core < client_core_limit; core++) {
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800336 per_client_config.add_core_list(dq.front());
337 dq.pop_front();
338 }
339 }
340 }
341
Craig Tiller6af9ed02015-03-02 22:42:10 -0800342 ClientArgs args;
Vijay Pai7d45cdb2016-02-01 13:00:19 -0800343 *args.mutable_setup() = per_client_config;
Vijay Pai90e73692015-08-05 19:15:36 -0700344 clients[i].stream =
vjpai63326282016-03-14 17:12:52 -0700345 clients[i].stub->RunClient(runsc::AllocContext(&contexts));
Vijay Paieed63fa2015-08-05 23:08:34 +0000346 GPR_ASSERT(clients[i].stream->Write(args));
Craig Tiller6af9ed02015-03-02 22:42:10 -0800347 ClientStatus init_status;
Vijay Paieed63fa2015-08-05 23:08:34 +0000348 GPR_ASSERT(clients[i].stream->Read(&init_status));
Craig Tiller2d0f36c2015-02-23 23:16:17 -0800349 }
350
Craig Tiller6af9ed02015-03-02 22:42:10 -0800351 // Let everything warmup
352 gpr_log(GPR_INFO, "Warming up");
Craig Tiller20b5fe92015-07-06 10:43:50 -0700353 gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME);
Craig Tiller677c50c2015-07-13 10:49:06 -0700354 gpr_sleep_until(
355 gpr_time_add(start, gpr_time_from_seconds(warmup_seconds, GPR_TIMESPAN)));
Craig Tiller6af9ed02015-03-02 22:42:10 -0800356
357 // Start a run
358 gpr_log(GPR_INFO, "Starting");
359 ServerArgs server_mark;
vjpai119c1032015-10-29 01:21:04 -0700360 server_mark.mutable_mark()->set_reset(true);
Craig Tiller6af9ed02015-03-02 22:42:10 -0800361 ClientArgs client_mark;
vjpai119c1032015-10-29 01:21:04 -0700362 client_mark.mutable_mark()->set_reset(true);
Vijay Paieed63fa2015-08-05 23:08:34 +0000363 for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
Vijay Pai82dd80a2015-03-24 10:36:08 -0700364 GPR_ASSERT(server->stream->Write(server_mark));
Craig Tiller6af9ed02015-03-02 22:42:10 -0800365 }
Vijay Paieed63fa2015-08-05 23:08:34 +0000366 for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
Vijay Pai82dd80a2015-03-24 10:36:08 -0700367 GPR_ASSERT(client->stream->Write(client_mark));
Craig Tiller6af9ed02015-03-02 22:42:10 -0800368 }
369 ServerStatus server_status;
370 ClientStatus client_status;
Vijay Paieed63fa2015-08-05 23:08:34 +0000371 for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
Vijay Pai82dd80a2015-03-24 10:36:08 -0700372 GPR_ASSERT(server->stream->Read(&server_status));
Craig Tiller6af9ed02015-03-02 22:42:10 -0800373 }
Vijay Paieed63fa2015-08-05 23:08:34 +0000374 for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
Vijay Pai82dd80a2015-03-24 10:36:08 -0700375 GPR_ASSERT(client->stream->Read(&client_status));
Craig Tiller2d0f36c2015-02-23 23:16:17 -0800376 }
377
Craig Tiller6af9ed02015-03-02 22:42:10 -0800378 // Wait some time
379 gpr_log(GPR_INFO, "Running");
Vijay Pai90e73692015-08-05 19:15:36 -0700380 // Use gpr_sleep_until rather than this_thread::sleep_until to support
381 // compilers that don't work with this_thread
Craig Tiller677c50c2015-07-13 10:49:06 -0700382 gpr_sleep_until(gpr_time_add(
Vijay Pai847baf62016-03-14 17:23:50 -0700383 start,
384 gpr_time_from_seconds(warmup_seconds + benchmark_seconds, GPR_TIMESPAN)));
Craig Tiller6af9ed02015-03-02 22:42:10 -0800385
386 // Finish a run
David Garcia Quintas08116502015-05-20 17:27:23 -0700387 std::unique_ptr<ScenarioResult> result(new ScenarioResult);
Jan Tattermuschf2ba7fe2016-04-14 12:14:17 -0700388 Histogram merged_latencies;
389
vjpai60a7e332016-02-26 10:30:17 -0800390 gpr_log(GPR_INFO, "Finishing clients");
Vijay Paieed63fa2015-08-05 23:08:34 +0000391 for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
Vijay Pai82dd80a2015-03-24 10:36:08 -0700392 GPR_ASSERT(client->stream->Write(client_mark));
Vijay Pai02eda412016-02-25 19:43:57 -0800393 GPR_ASSERT(client->stream->WritesDone());
Craig Tiller6af9ed02015-03-02 22:42:10 -0800394 }
Vijay Paieed63fa2015-08-05 23:08:34 +0000395 for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
Vijay Pai82dd80a2015-03-24 10:36:08 -0700396 GPR_ASSERT(client->stream->Read(&client_status));
Craig Tillerf2825142015-03-03 17:15:36 -0800397 const auto& stats = client_status.stats();
Jan Tattermuschf2ba7fe2016-04-14 12:14:17 -0700398 merged_latencies.MergeProto(stats.latencies());
399 result->add_client_stats()->CopyFrom(stats);
Vijay Pai02eda412016-02-25 19:43:57 -0800400 GPR_ASSERT(!client->stream->Read(&client_status));
Craig Tiller6af9ed02015-03-02 22:42:10 -0800401 }
Vijay Paieed63fa2015-08-05 23:08:34 +0000402 for (auto client = &clients[0]; client != &clients[num_clients]; client++) {
Yang Gaoc1a2c312015-06-16 10:59:46 -0700403 GPR_ASSERT(client->stream->Finish().ok());
Craig Tiller6af9ed02015-03-02 22:42:10 -0800404 }
vjpai60a7e332016-02-26 10:30:17 -0800405 delete[] clients;
406
Jan Tattermuschf2ba7fe2016-04-14 12:14:17 -0700407 merged_latencies.FillProto(result->mutable_latencies());
408
vjpai60a7e332016-02-26 10:30:17 -0800409 gpr_log(GPR_INFO, "Finishing servers");
410 for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
411 GPR_ASSERT(server->stream->Write(server_mark));
412 GPR_ASSERT(server->stream->WritesDone());
413 }
414 for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
415 GPR_ASSERT(server->stream->Read(&server_status));
Jan Tattermuschf2ba7fe2016-04-14 12:14:17 -0700416 result->add_server_stats()->CopyFrom(server_status.stats());
417 result->add_server_cores(server_status.cores());
vjpai60a7e332016-02-26 10:30:17 -0800418 GPR_ASSERT(!server->stream->Read(&server_status));
419 }
Vijay Paieed63fa2015-08-05 23:08:34 +0000420 for (auto server = &servers[0]; server != &servers[num_servers]; server++) {
Yang Gaoc1a2c312015-06-16 10:59:46 -0700421 GPR_ASSERT(server->stream->Finish().ok());
Craig Tiller2d0f36c2015-02-23 23:16:17 -0800422 }
vjpai60a7e332016-02-26 10:30:17 -0800423
vjpaib1db8692015-08-11 22:41:02 -0700424 delete[] servers;
Jan Tattermusch33c161d2016-04-15 14:45:49 -0700425
426 postprocess_scenario_result(result.get());
Craig Tillerf2825142015-03-03 17:15:36 -0800427 return result;
Craig Tiller4ef7a292015-02-23 17:29:01 -0800428}
vjpai21e5d2b2016-02-02 09:36:36 -0800429
430void RunQuit() {
431 // Get client, server lists
Vijay Pai20664432016-02-02 11:48:12 -0800432 auto workers = get_workers("QPS_WORKERS");
vjpai21e5d2b2016-02-02 09:36:36 -0800433 for (size_t i = 0; i < workers.size(); i++) {
Vijay Pai847baf62016-03-14 17:23:50 -0700434 auto stub = WorkerService::NewStub(
Vijay Pai2ed337a2016-02-02 09:43:35 -0800435 CreateChannel(workers[i], InsecureChannelCredentials()));
vjpai21e5d2b2016-02-02 09:36:36 -0800436 Void dummy;
437 grpc::ClientContext ctx;
438 GPR_ASSERT(stub->QuitWorker(&ctx, dummy, &dummy).ok());
439 }
440}
441
Craig Tillerf2825142015-03-03 17:15:36 -0800442} // namespace testing
443} // namespace grpc