diff options
author | Craig Tiller <ctiller@google.com> | 2016-04-21 17:07:36 -0700 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2016-04-21 17:07:36 -0700 |
commit | 7beea147e506b57a9656976001a1360e755a2e9b (patch) | |
tree | 57d098e53d213dfe21e1bf40b7693ff2936901d4 /test/cpp/qps | |
parent | 788a25365d022d9797de444799c57842a6fa0603 (diff) | |
parent | 5a56891eb6b1591e97d36072ac067d762aecf07e (diff) |
Merge github.com:grpc/grpc into strong-includes
Diffstat (limited to 'test/cpp/qps')
-rw-r--r-- | test/cpp/qps/client.h | 14 | ||||
-rw-r--r-- | test/cpp/qps/driver.cc | 61 | ||||
-rw-r--r-- | test/cpp/qps/driver.h | 23 | ||||
-rw-r--r-- | test/cpp/qps/interarrival.h | 56 | ||||
-rwxr-xr-x | test/cpp/qps/qps-sweep.sh | 170 | ||||
-rw-r--r-- | test/cpp/qps/qps_driver.cc | 213 | ||||
-rw-r--r-- | test/cpp/qps/qps_interarrival_test.cc | 6 | ||||
-rw-r--r-- | test/cpp/qps/qps_json_driver.cc | 33 | ||||
-rw-r--r-- | test/cpp/qps/report.cc | 117 | ||||
-rw-r--r-- | test/cpp/qps/report.h | 26 | ||||
-rwxr-xr-x | test/cpp/qps/single_run_localhost.sh | 56 |
11 files changed, 118 insertions, 657 deletions
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index e958141d4e..5a9027a4a2 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -173,20 +173,6 @@ class Client { random_dist.reset( new ExpDist(load.poisson().offered_load() / num_threads)); break; - case LoadParams::kUniform: - random_dist.reset( - new UniformDist(load.uniform().interarrival_lo() * num_threads, - load.uniform().interarrival_hi() * num_threads)); - break; - case LoadParams::kDeterm: - random_dist.reset( - new DetDist(num_threads / load.determ().offered_load())); - break; - case LoadParams::kPareto: - random_dist.reset( - new ParetoDist(load.pareto().interarrival_base() * num_threads, - load.pareto().alpha())); - break; default: GPR_ASSERT(false); } diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index c87ad6461d..2583ceb819 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -52,6 +52,7 @@ #include "test/cpp/qps/driver.h" #include "test/cpp/qps/histogram.h" #include "test/cpp/qps/qps_worker.h" +#include "test/cpp/qps/stats.h" using std::list; using std::thread; @@ -115,6 +116,47 @@ static deque<string> get_workers(const string& name) { } } +// helpers for postprocess_scenario_result +static double WallTime(ClientStats s) { return s.time_elapsed(); } +static double SystemTime(ClientStats s) { return s.time_system(); } +static double UserTime(ClientStats s) { return s.time_user(); } +static double ServerWallTime(ServerStats s) { return s.time_elapsed(); } +static double ServerSystemTime(ServerStats s) { return s.time_system(); } +static double ServerUserTime(ServerStats s) { return s.time_user(); } +static int Cores(int n) { return n; } + +// Postprocess ScenarioResult and populate result summary. +static void postprocess_scenario_result(ScenarioResult* result) { + Histogram histogram; + histogram.MergeProto(result->latencies()); + + auto qps = histogram.Count() / average(result->client_stats(), WallTime); + auto qps_per_server_core = qps / sum(result->server_cores(), Cores); + + result->mutable_summary()->set_qps(qps); + result->mutable_summary()->set_qps_per_server_core(qps_per_server_core); + result->mutable_summary()->set_latency_50(histogram.Percentile(50)); + result->mutable_summary()->set_latency_90(histogram.Percentile(90)); + result->mutable_summary()->set_latency_95(histogram.Percentile(95)); + result->mutable_summary()->set_latency_99(histogram.Percentile(99)); + result->mutable_summary()->set_latency_999(histogram.Percentile(99.9)); + + auto server_system_time = 100.0 * + sum(result->server_stats(), ServerSystemTime) / + sum(result->server_stats(), ServerWallTime); + auto server_user_time = 100.0 * sum(result->server_stats(), ServerUserTime) / + sum(result->server_stats(), ServerWallTime); + auto client_system_time = 100.0 * sum(result->client_stats(), SystemTime) / + sum(result->client_stats(), WallTime); + auto client_user_time = 100.0 * sum(result->client_stats(), UserTime) / + sum(result->client_stats(), WallTime); + + result->mutable_summary()->set_server_system_time(server_system_time); + result->mutable_summary()->set_server_user_time(server_user_time); + result->mutable_summary()->set_client_system_time(client_system_time); + result->mutable_summary()->set_client_user_time(client_user_time); +} + // Namespace for classes and functions used only in RunScenario // Using this rather than local definitions to workaround gcc-4.4 limitations // regarding using templates without linkage @@ -343,8 +385,8 @@ std::unique_ptr<ScenarioResult> RunScenario( // Finish a run std::unique_ptr<ScenarioResult> result(new ScenarioResult); - result->client_config = result_client_config; - result->server_config = result_server_config; + Histogram merged_latencies; + gpr_log(GPR_INFO, "Finishing clients"); for (auto client = &clients[0]; client != &clients[num_clients]; client++) { GPR_ASSERT(client->stream->Write(client_mark)); @@ -353,9 +395,8 @@ std::unique_ptr<ScenarioResult> RunScenario( for (auto client = &clients[0]; client != &clients[num_clients]; client++) { GPR_ASSERT(client->stream->Read(&client_status)); const auto& stats = client_status.stats(); - result->latencies.MergeProto(stats.latencies()); - result->client_resources.emplace_back( - stats.time_elapsed(), stats.time_user(), stats.time_system(), -1); + merged_latencies.MergeProto(stats.latencies()); + result->add_client_stats()->CopyFrom(stats); GPR_ASSERT(!client->stream->Read(&client_status)); } for (auto client = &clients[0]; client != &clients[num_clients]; client++) { @@ -363,6 +404,8 @@ std::unique_ptr<ScenarioResult> RunScenario( } delete[] clients; + merged_latencies.FillProto(result->mutable_latencies()); + gpr_log(GPR_INFO, "Finishing servers"); for (auto server = &servers[0]; server != &servers[num_servers]; server++) { GPR_ASSERT(server->stream->Write(server_mark)); @@ -370,10 +413,8 @@ std::unique_ptr<ScenarioResult> RunScenario( } for (auto server = &servers[0]; server != &servers[num_servers]; server++) { GPR_ASSERT(server->stream->Read(&server_status)); - const auto& stats = server_status.stats(); - result->server_resources.emplace_back( - stats.time_elapsed(), stats.time_user(), stats.time_system(), - server_status.cores()); + result->add_server_stats()->CopyFrom(server_status.stats()); + result->add_server_cores(server_status.cores()); GPR_ASSERT(!server->stream->Read(&server_status)); } for (auto server = &servers[0]; server != &servers[num_servers]; server++) { @@ -381,6 +422,8 @@ std::unique_ptr<ScenarioResult> RunScenario( } delete[] servers; + + postprocess_scenario_result(result.get()); return result; } diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h index 21e51529d5..3a5cf138f1 100644 --- a/test/cpp/qps/driver.h +++ b/test/cpp/qps/driver.h @@ -41,29 +41,6 @@ namespace grpc { namespace testing { -class ResourceUsage { - public: - ResourceUsage(double w, double u, double s, int c) - : wall_time_(w), user_time_(u), system_time_(s), cores_(c) {} - double wall_time() const { return wall_time_; } - double user_time() const { return user_time_; } - double system_time() const { return system_time_; } - int cores() const { return cores_; } - - private: - double wall_time_; - double user_time_; - double system_time_; - int cores_; -}; - -struct ScenarioResult { - Histogram latencies; - std::vector<ResourceUsage> client_resources; - std::vector<ResourceUsage> server_resources; - ClientConfig client_config; - ServerConfig server_config; -}; std::unique_ptr<ScenarioResult> RunScenario( const grpc::testing::ClientConfig& client_config, size_t num_clients, diff --git a/test/cpp/qps/interarrival.h b/test/cpp/qps/interarrival.h index 0cc78533ce..0980d5e8ba 100644 --- a/test/cpp/qps/interarrival.h +++ b/test/cpp/qps/interarrival.h @@ -82,62 +82,6 @@ class ExpDist GRPC_FINAL : public RandomDistInterface { double lambda_recip_; }; -// UniformDist implements a random distribution that has -// interarrival time uniformly spread between [lo,hi). The -// mean interarrival time is (lo+hi)/2. For more information, -// see http://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29 - -class UniformDist GRPC_FINAL : public RandomDistInterface { - public: - UniformDist(double lo, double hi) : lo_(lo), range_(hi - lo) {} - ~UniformDist() GRPC_OVERRIDE {} - double transform(double uni) const GRPC_OVERRIDE { - return uni * range_ + lo_; - } - - private: - double lo_; - double range_; -}; - -// DetDist provides a random distribution with interarrival time -// of val. Note that this is not additive, so using this on multiple -// flows of control (threads within the same client or separate -// clients) will not preserve any deterministic interarrival gap across -// requests. - -class DetDist GRPC_FINAL : public RandomDistInterface { - public: - explicit DetDist(double val) : val_(val) {} - ~DetDist() GRPC_OVERRIDE {} - double transform(double uni) const GRPC_OVERRIDE { return val_; } - - private: - double val_; -}; - -// ParetoDist provides a random distribution with interarrival time -// spread according to a Pareto (heavy-tailed) distribution. In this -// model, many interarrival times are close to the base, but a sufficient -// number will be high (up to infinity) as to disturb the mean. It is a -// good representation of the response times of data center jobs. See -// http://en.wikipedia.org/wiki/Pareto_distribution - -class ParetoDist GRPC_FINAL : public RandomDistInterface { - public: - ParetoDist(double base, double alpha) - : base_(base), alpha_recip_(1.0 / alpha) {} - ~ParetoDist() GRPC_OVERRIDE {} - double transform(double uni) const GRPC_OVERRIDE { - // Note: Use 1.0-uni above to avoid div by zero if uni is 0 - return base_ / pow(1.0 - uni, alpha_recip_); - } - - private: - double base_; - double alpha_recip_; -}; - // A class library for generating pseudo-random interarrival times // in an efficient re-entrant way. The random table is built at construction // time, and each call must include the thread id of the invoker diff --git a/test/cpp/qps/qps-sweep.sh b/test/cpp/qps/qps-sweep.sh deleted file mode 100755 index 8f7fb92772..0000000000 --- a/test/cpp/qps/qps-sweep.sh +++ /dev/null @@ -1,170 +0,0 @@ -#!/bin/sh - -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -if [ x"$QPS_WORKERS" == x ]; then - echo Error: Must set QPS_WORKERS variable in form \ - "host:port,host:port,..." 1>&2 - exit 1 -fi - -bins=`find . .. ../.. ../../.. -name bins | head -1` - -# Print out each command that gets executed -set -x - -# -# Specify parameters used in some of the tests -# - -# big is the size in bytes of large messages (0 is the size otherwise) -big=65536 - -# wide is the number of client channels in multi-channel tests (1 otherwise) -wide=64 - -# deep is the number of RPCs outstanding on a channel in non-ping-pong tests -# (the value used is 1 otherwise) -deep=100 - -# half is half the count of worker processes, used in the crossbar scenario -# that uses equal clients and servers. The other scenarios use only 1 server -# and either 1 client or N-1 clients as appropriate -half=`echo $QPS_WORKERS | awk -F, '{print int(NF/2)}'` - -for secure in true false; do - # Scenario 1: generic async streaming ping-pong (contentionless latency) - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=1 \ - --client_channels=1 --bbuf_req_size=0 --bbuf_resp_size=0 \ - --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \ - --num_servers=1 --num_clients=1 - - # Scenario 2: generic async streaming "unconstrained" (QPS) - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \ - --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \ - --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \ - --num_servers=1 --num_clients=0 2>&1 | tee /tmp/qps-test.$$ - - # Scenario 2b: QPS with a single server core - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \ - --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \ - --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \ - --num_servers=1 --num_clients=0 --server_core_limit=1 - - # Scenario 2c: protobuf-based QPS - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_SERVER --outstanding_rpcs_per_channel=$deep \ - --client_channels=$wide --simple_req_size=0 --simple_resp_size=0 \ - --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \ - --num_servers=1 --num_clients=0 - - # Scenario 3: Latency at sub-peak load (all clients equally loaded) - for loadfactor in 0.2 0.5 0.7; do - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \ - --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \ - --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \ - --num_servers=1 --num_clients=0 --poisson_load=`awk -v lf=$loadfactor \ - '$5 == "QPS:" {print int(lf * $6); exit}' /tmp/qps-test.$$` - done - - rm /tmp/qps-test.$$ - - # Scenario 4: Single-channel bidirectional throughput test (like TCP_STREAM). - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \ - --client_channels=1 --bbuf_req_size=$big --bbuf_resp_size=$big \ - --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \ - --num_servers=1 --num_clients=1 - - # Scenario 5: Sync unary ping-pong with protobufs - "$bins"/opt/qps_driver --rpc_type=UNARY --client_type=SYNC_CLIENT \ - --server_type=SYNC_SERVER --outstanding_rpcs_per_channel=1 \ - --client_channels=1 --simple_req_size=0 --simple_resp_size=0 \ - --secure_test=$secure --num_servers=1 --num_clients=1 - - # Scenario 6: Sync streaming ping-pong with protobufs - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=SYNC_CLIENT \ - --server_type=SYNC_SERVER --outstanding_rpcs_per_channel=1 \ - --client_channels=1 --simple_req_size=0 --simple_resp_size=0 \ - --secure_test=$secure --num_servers=1 --num_clients=1 - - # Scenario 7: Async unary ping-pong with protobufs - "$bins"/opt/qps_driver --rpc_type=UNARY --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_SERVER --outstanding_rpcs_per_channel=1 \ - --client_channels=1 --simple_req_size=0 --simple_resp_size=0 \ - --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \ - --num_servers=1 --num_clients=1 - - # Scenario 8: Async streaming ping-pong with protobufs - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_SERVER --outstanding_rpcs_per_channel=1 \ - --client_channels=1 --simple_req_size=0 --simple_resp_size=0 \ - --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \ - --num_servers=1 --num_clients=1 - - # Scenario 9: Crossbar QPS test - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \ - --client_channels=$wide --bbuf_req_size=0 --bbuf_resp_size=0 \ - --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \ - --num_servers=$half --num_clients=0 - - # Scenario 10: Multi-channel bidir throughput test - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=1 \ - --client_channels=$wide --bbuf_req_size=$big --bbuf_resp_size=$big \ - --async_client_threads=0 --async_server_threads=0 --secure_test=$secure \ - --num_servers=1 --num_clients=1 - - # Scenario 11: Single-channel request throughput test - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \ - --client_channels=1 --bbuf_req_size=$big --bbuf_resp_size=0 \ - --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \ - --num_servers=1 --num_clients=1 - - # Scenario 12: Single-channel response throughput test - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_GENERIC_SERVER --outstanding_rpcs_per_channel=$deep \ - --client_channels=1 --bbuf_req_size=0 --bbuf_resp_size=$big \ - --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \ - --num_servers=1 --num_clients=1 - - # Scenario 13: Single-channel bidirectional protobuf throughput test - "$bins"/opt/qps_driver --rpc_type=STREAMING --client_type=ASYNC_CLIENT \ - --server_type=ASYNC_SERVER --outstanding_rpcs_per_channel=$deep \ - --client_channels=1 --simple_req_size=$big --simple_resp_size=$big \ - --async_client_threads=1 --async_server_threads=1 --secure_test=$secure \ - --num_servers=1 --num_clients=1 -done diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc deleted file mode 100644 index e412c6919a..0000000000 --- a/test/cpp/qps/qps_driver.cc +++ /dev/null @@ -1,213 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include <memory> -#include <set> - -#include <gflags/gflags.h> -#include <grpc/support/log.h> - -#include "test/cpp/qps/driver.h" -#include "test/cpp/qps/report.h" -#include "test/cpp/util/benchmark_config.h" - -DEFINE_int32(num_clients, 1, "Number of client binaries"); -DEFINE_int32(num_servers, 1, "Number of server binaries"); - -DEFINE_int32(warmup_seconds, 5, "Warmup time (in seconds)"); -DEFINE_int32(benchmark_seconds, 30, "Benchmark time (in seconds)"); -DEFINE_int32(local_workers, 0, "Number of local workers to start"); - -// Server config -DEFINE_int32(async_server_threads, 1, "Number of threads for async servers"); -DEFINE_string(server_type, "SYNC_SERVER", "Server type"); -DEFINE_int32(server_core_limit, -1, "Limit on server cores to use"); - -// Client config -DEFINE_string(rpc_type, "UNARY", "Type of RPC: UNARY or STREAMING"); -DEFINE_int32(outstanding_rpcs_per_channel, 1, - "Number of outstanding rpcs per channel"); -DEFINE_int32(client_channels, 1, "Number of client channels"); - -DEFINE_int32(simple_req_size, -1, "Simple proto request payload size"); -DEFINE_int32(simple_resp_size, -1, "Simple proto response payload size"); -DEFINE_int32(bbuf_req_size, -1, "Byte-buffer request payload size"); -DEFINE_int32(bbuf_resp_size, -1, "Byte-buffer response payload size"); - -DEFINE_string(client_type, "SYNC_CLIENT", "Client type"); -DEFINE_int32(async_client_threads, 1, "Async client threads"); - -DEFINE_double(poisson_load, -1.0, "Poisson offered load (qps)"); -DEFINE_double(uniform_lo, -1.0, "Uniform low interarrival time (us)"); -DEFINE_double(uniform_hi, -1.0, "Uniform high interarrival time (us)"); -DEFINE_double(determ_load, -1.0, "Deterministic offered load (qps)"); -DEFINE_double(pareto_base, -1.0, "Pareto base interarrival time (us)"); -DEFINE_double(pareto_alpha, -1.0, "Pareto alpha value"); - -DEFINE_int32(client_core_limit, -1, "Limit on client cores to use"); - -DEFINE_bool(secure_test, false, "Run a secure test"); - -DEFINE_bool(quit, false, "Quit the workers"); - -using grpc::testing::ClientConfig; -using grpc::testing::ServerConfig; -using grpc::testing::ClientType; -using grpc::testing::ServerType; -using grpc::testing::RpcType; -using grpc::testing::ResourceUsage; -using grpc::testing::SecurityParams; - -namespace grpc { -namespace testing { - -static void QpsDriver() { - if (FLAGS_quit) { - RunQuit(); - return; - } - - RpcType rpc_type; - GPR_ASSERT(RpcType_Parse(FLAGS_rpc_type, &rpc_type)); - - ClientType client_type; - ServerType server_type; - GPR_ASSERT(ClientType_Parse(FLAGS_client_type, &client_type)); - GPR_ASSERT(ServerType_Parse(FLAGS_server_type, &server_type)); - - ClientConfig client_config; - client_config.set_client_type(client_type); - client_config.set_outstanding_rpcs_per_channel( - FLAGS_outstanding_rpcs_per_channel); - client_config.set_client_channels(FLAGS_client_channels); - - // Decide which type to use based on the response type - if (FLAGS_simple_resp_size >= 0) { - auto params = - client_config.mutable_payload_config()->mutable_simple_params(); - params->set_resp_size(FLAGS_simple_resp_size); - if (FLAGS_simple_req_size >= 0) { - params->set_req_size(FLAGS_simple_req_size); - } - } else if (FLAGS_bbuf_resp_size >= 0) { - auto params = - client_config.mutable_payload_config()->mutable_bytebuf_params(); - params->set_resp_size(FLAGS_bbuf_resp_size); - if (FLAGS_bbuf_req_size >= 0) { - params->set_req_size(FLAGS_bbuf_req_size); - } - } else { - // set a reasonable default: proto but no payload - client_config.mutable_payload_config()->mutable_simple_params(); - } - - client_config.set_async_client_threads(FLAGS_async_client_threads); - client_config.set_rpc_type(rpc_type); - - // set up the load parameters - if (FLAGS_poisson_load > 0.0) { - auto poisson = client_config.mutable_load_params()->mutable_poisson(); - poisson->set_offered_load(FLAGS_poisson_load); - } else if (FLAGS_uniform_lo > 0.0) { - auto uniform = client_config.mutable_load_params()->mutable_uniform(); - uniform->set_interarrival_lo(FLAGS_uniform_lo / 1e6); - uniform->set_interarrival_hi(FLAGS_uniform_hi / 1e6); - } else if (FLAGS_determ_load > 0.0) { - auto determ = client_config.mutable_load_params()->mutable_determ(); - determ->set_offered_load(FLAGS_determ_load); - } else if (FLAGS_pareto_base > 0.0) { - auto pareto = client_config.mutable_load_params()->mutable_pareto(); - pareto->set_interarrival_base(FLAGS_pareto_base / 1e6); - pareto->set_alpha(FLAGS_pareto_alpha); - } else { - client_config.mutable_load_params()->mutable_closed_loop(); - // No further load parameters to set up for closed loop - } - - client_config.mutable_histogram_params()->set_resolution( - Histogram::default_resolution()); - client_config.mutable_histogram_params()->set_max_possible( - Histogram::default_max_possible()); - - if (FLAGS_client_core_limit > 0) { - client_config.set_core_limit(FLAGS_client_core_limit); - } - - ServerConfig server_config; - server_config.set_server_type(server_type); - server_config.set_async_server_threads(FLAGS_async_server_threads); - - if (FLAGS_server_core_limit > 0) { - server_config.set_core_limit(FLAGS_server_core_limit); - } - - if (FLAGS_bbuf_resp_size >= 0) { - *server_config.mutable_payload_config() = client_config.payload_config(); - } - - if (FLAGS_secure_test) { - // Set up security params - SecurityParams security; - security.set_use_test_ca(true); - security.set_server_host_override("foo.test.google.fr"); - client_config.mutable_security_params()->CopyFrom(security); - server_config.mutable_security_params()->CopyFrom(security); - } - - // Make sure that if we are performing a generic (bytebuf) test - // that we are also using async streaming - GPR_ASSERT(!client_config.payload_config().has_bytebuf_params() || - (client_config.client_type() == ASYNC_CLIENT && - client_config.rpc_type() == STREAMING && - server_config.server_type() == ASYNC_GENERIC_SERVER)); - - const auto result = RunScenario( - client_config, FLAGS_num_clients, server_config, FLAGS_num_servers, - FLAGS_warmup_seconds, FLAGS_benchmark_seconds, FLAGS_local_workers); - - GetReporter()->ReportQPS(*result); - GetReporter()->ReportQPSPerCore(*result); - GetReporter()->ReportLatency(*result); - GetReporter()->ReportTimes(*result); -} - -} // namespace testing -} // namespace grpc - -int main(int argc, char** argv) { - grpc::testing::InitBenchmark(&argc, &argv, true); - - grpc::testing::QpsDriver(); - - return 0; -} diff --git a/test/cpp/qps/qps_interarrival_test.cc b/test/cpp/qps/qps_interarrival_test.cc index 48585af756..4055c8a718 100644 --- a/test/cpp/qps/qps_interarrival_test.cc +++ b/test/cpp/qps/qps_interarrival_test.cc @@ -63,14 +63,8 @@ static void RunTest(RandomDistInterface &&r, int threads, std::string title) { } using grpc::testing::ExpDist; -using grpc::testing::DetDist; -using grpc::testing::UniformDist; -using grpc::testing::ParetoDist; int main(int argc, char **argv) { RunTest(ExpDist(10.0), 5, std::string("Exponential(10)")); - RunTest(DetDist(5.0), 5, std::string("Det(5)")); - RunTest(UniformDist(0.0, 10.0), 5, std::string("Uniform(0,10)")); - RunTest(ParetoDist(1.0, 1.0), 5, std::string("Pareto(1,1)")); return 0; } diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc index 8af4e291a9..e47d48a4f7 100644 --- a/test/cpp/qps/qps_json_driver.cc +++ b/test/cpp/qps/qps_json_driver.cc @@ -48,6 +48,7 @@ DEFINE_string(scenarios_file, "", "JSON file containing an array of Scenario objects"); DEFINE_string(scenarios_json, "", "JSON string containing an array of Scenario objects"); +DEFINE_bool(quit, false, "Quit the workers"); namespace grpc { namespace testing { @@ -55,12 +56,17 @@ namespace testing { static void QpsDriver() { grpc::string json; - if (FLAGS_scenarios_file != "") { - if (FLAGS_scenarios_json != "") { - gpr_log(GPR_ERROR, - "Only one of --scenarios_file or --scenarios_json must be set"); - abort(); - } + bool scfile = (FLAGS_scenarios_file != ""); + bool scjson = (FLAGS_scenarios_json != ""); + if ((!scfile && !scjson && !FLAGS_quit) || + (scfile && (scjson || FLAGS_quit)) || (scjson && FLAGS_quit)) { + gpr_log(GPR_ERROR, + "Exactly one of --scenarios_file, --scenarios_json, " + "or --quit must be set"); + abort(); + } + + if (scfile) { // Read the json data from disk FILE *json_file = fopen(FLAGS_scenarios_file.c_str(), "r"); GPR_ASSERT(json_file != NULL); @@ -72,12 +78,11 @@ static void QpsDriver() { fclose(json_file); json = grpc::string(data, data + len); delete[] data; - } else if (FLAGS_scenarios_json != "") { + } else if (scjson) { json = FLAGS_scenarios_json.c_str(); - } else { - gpr_log(GPR_ERROR, - "One of --scenarios_file or --scenarios_json must be set"); - abort(); + } else if (FLAGS_quit) { + RunQuit(); + return; } // Parse into an array of scenarios @@ -87,12 +92,16 @@ static void QpsDriver() { for (int i = 0; i < scenarios.scenarios_size(); i++) { const Scenario &scenario = scenarios.scenarios(i); std::cerr << "RUNNING SCENARIO: " << scenario.name() << "\n"; - const auto result = + auto result = RunScenario(scenario.client_config(), scenario.num_clients(), scenario.server_config(), scenario.num_servers(), scenario.warmup_seconds(), scenario.benchmark_seconds(), scenario.spawn_local_worker_count()); + // Amend the result with scenario config. Eventually we should adjust + // RunScenario contract so we don't need to touch the result here. + result->mutable_scenario()->CopyFrom(scenario); + GetReporter()->ReportQPS(*result); GetReporter()->ReportQPSPerCore(*result); GetReporter()->ReportLatency(*result); diff --git a/test/cpp/qps/report.cc b/test/cpp/qps/report.cc index b230eb441e..3ae41399cf 100644 --- a/test/cpp/qps/report.cc +++ b/test/cpp/qps/report.cc @@ -33,6 +33,11 @@ #include "test/cpp/qps/report.h" +#include <fstream> + +#include <google/protobuf/util/json_util.h> +#include <google/protobuf/util/type_resolver_util.h> + #include <grpc/support/log.h> #include "test/cpp/qps/driver.h" #include "test/cpp/qps/stats.h" @@ -40,11 +45,6 @@ namespace grpc { namespace testing { -static double WallTime(ResourceUsage u) { return u.wall_time(); } -static double UserTime(ResourceUsage u) { return u.user_time(); } -static double SystemTime(ResourceUsage u) { return u.system_time(); } -static int Cores(ResourceUsage u) { return u.cores(); } - void CompositeReporter::add(std::unique_ptr<Reporter> reporter) { reporters_.emplace_back(std::move(reporter)); } @@ -74,102 +74,63 @@ void CompositeReporter::ReportTimes(const ScenarioResult& result) { } void GprLogReporter::ReportQPS(const ScenarioResult& result) { - gpr_log( - GPR_INFO, "QPS: %.1f", - result.latencies.Count() / average(result.client_resources, WallTime)); + gpr_log(GPR_INFO, "QPS: %.1f", result.summary().qps()); } void GprLogReporter::ReportQPSPerCore(const ScenarioResult& result) { - auto qps = - result.latencies.Count() / average(result.client_resources, WallTime); - - gpr_log(GPR_INFO, "QPS: %.1f (%.1f/server core)", qps, - qps / sum(result.server_resources, Cores)); + gpr_log(GPR_INFO, "QPS: %.1f (%.1f/server core)", result.summary().qps(), + result.summary().qps_per_server_core()); } void GprLogReporter::ReportLatency(const ScenarioResult& result) { gpr_log(GPR_INFO, "Latencies (50/90/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f/%.1f us", - result.latencies.Percentile(50) / 1000, - result.latencies.Percentile(90) / 1000, - result.latencies.Percentile(95) / 1000, - result.latencies.Percentile(99) / 1000, - result.latencies.Percentile(99.9) / 1000); + result.summary().latency_50() / 1000, + result.summary().latency_90() / 1000, + result.summary().latency_95() / 1000, + result.summary().latency_99() / 1000, + result.summary().latency_999() / 1000); } void GprLogReporter::ReportTimes(const ScenarioResult& result) { gpr_log(GPR_INFO, "Server system time: %.2f%%", - 100.0 * sum(result.server_resources, SystemTime) / - sum(result.server_resources, WallTime)); + result.summary().server_system_time()); gpr_log(GPR_INFO, "Server user time: %.2f%%", - 100.0 * sum(result.server_resources, UserTime) / - sum(result.server_resources, WallTime)); + result.summary().server_user_time()); gpr_log(GPR_INFO, "Client system time: %.2f%%", - 100.0 * sum(result.client_resources, SystemTime) / - sum(result.client_resources, WallTime)); + result.summary().client_system_time()); gpr_log(GPR_INFO, "Client user time: %.2f%%", - 100.0 * sum(result.client_resources, UserTime) / - sum(result.client_resources, WallTime)); + result.summary().client_user_time()); } -void PerfDbReporter::ReportQPS(const ScenarioResult& result) { - auto qps = - result.latencies.Count() / average(result.client_resources, WallTime); - - perf_db_client_.setQps(qps); - perf_db_client_.setConfigs(result.client_config, result.server_config); +void JsonReporter::ReportQPS(const ScenarioResult& result) { + std::unique_ptr<google::protobuf::util::TypeResolver> type_resolver( + google::protobuf::util::NewTypeResolverForDescriptorPool( + "type.googleapis.com", + google::protobuf::DescriptorPool::generated_pool())); + grpc::string binary; + grpc::string json_string; + result.SerializeToString(&binary); + auto status = BinaryToJsonString( + type_resolver.get(), "type.googleapis.com/grpc.testing.ScenarioResult", + binary, &json_string); + GPR_ASSERT(status.ok()); + + std::ofstream output_file(report_file_); + output_file << json_string; + output_file.close(); } -void PerfDbReporter::ReportQPSPerCore(const ScenarioResult& result) { - auto qps = - result.latencies.Count() / average(result.client_resources, WallTime); - - auto qps_per_core = qps / sum(result.server_resources, Cores); - - perf_db_client_.setQps(qps); - perf_db_client_.setQpsPerCore(qps_per_core); - perf_db_client_.setConfigs(result.client_config, result.server_config); -} - -void PerfDbReporter::ReportLatency(const ScenarioResult& result) { - perf_db_client_.setLatencies(result.latencies.Percentile(50) / 1000, - result.latencies.Percentile(90) / 1000, - result.latencies.Percentile(95) / 1000, - result.latencies.Percentile(99) / 1000, - result.latencies.Percentile(99.9) / 1000); - perf_db_client_.setConfigs(result.client_config, result.server_config); +void JsonReporter::ReportQPSPerCore(const ScenarioResult& result) { + // NOP - all reporting is handled by ReportQPS. } -void PerfDbReporter::ReportTimes(const ScenarioResult& result) { - const double server_system_time = 100.0 * - sum(result.server_resources, SystemTime) / - sum(result.server_resources, WallTime); - const double server_user_time = 100.0 * - sum(result.server_resources, UserTime) / - sum(result.server_resources, WallTime); - const double client_system_time = 100.0 * - sum(result.client_resources, SystemTime) / - sum(result.client_resources, WallTime); - const double client_user_time = 100.0 * - sum(result.client_resources, UserTime) / - sum(result.client_resources, WallTime); - - perf_db_client_.setTimes(server_system_time, server_user_time, - client_system_time, client_user_time); - perf_db_client_.setConfigs(result.client_config, result.server_config); +void JsonReporter::ReportLatency(const ScenarioResult& result) { + // NOP - all reporting is handled by ReportQPS. } -void PerfDbReporter::SendData() { - // send data to performance database - bool data_state = - perf_db_client_.sendData(hashed_id_, test_name_, sys_info_, tag_); - - // check state of data sending - if (data_state) { - gpr_log(GPR_INFO, "Data sent to performance database successfully"); - } else { - gpr_log(GPR_INFO, "Data could not be sent to performance database"); - } +void JsonReporter::ReportTimes(const ScenarioResult& result) { + // NOP - all reporting is handled by ReportQPS. } } // namespace testing diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h index 5caf3fe69a..8f04d84124 100644 --- a/test/cpp/qps/report.h +++ b/test/cpp/qps/report.h @@ -104,33 +104,19 @@ class GprLogReporter : public Reporter { void ReportTimes(const ScenarioResult& result) GRPC_OVERRIDE; }; -/** Reporter for performance database tool */ -class PerfDbReporter : public Reporter { +/** Dumps the report to a JSON file. */ +class JsonReporter : public Reporter { public: - PerfDbReporter(const string& name, const string& hashed_id, - const string& test_name, const string& sys_info, - const string& server_address, const string& tag) - : Reporter(name), - hashed_id_(hashed_id), - test_name_(test_name), - sys_info_(sys_info), - tag_(tag) { - perf_db_client_.init(grpc::CreateChannel( - server_address, grpc::InsecureChannelCredentials())); - } - ~PerfDbReporter() GRPC_OVERRIDE { SendData(); }; + JsonReporter(const string& name, const string& report_file) + : Reporter(name), report_file_(report_file) {} private: - PerfDbClient perf_db_client_; - std::string hashed_id_; - std::string test_name_; - std::string sys_info_; - std::string tag_; void ReportQPS(const ScenarioResult& result) GRPC_OVERRIDE; void ReportQPSPerCore(const ScenarioResult& result) GRPC_OVERRIDE; void ReportLatency(const ScenarioResult& result) GRPC_OVERRIDE; void ReportTimes(const ScenarioResult& result) GRPC_OVERRIDE; - void SendData(); + + const string report_file_; }; } // namespace testing diff --git a/test/cpp/qps/single_run_localhost.sh b/test/cpp/qps/single_run_localhost.sh deleted file mode 100755 index f5356f1834..0000000000 --- a/test/cpp/qps/single_run_localhost.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# performs a single qps run with one client and one server - -set -ex - -cd $(dirname $0)/../../.. - -killall qps_worker || true - -config=opt - -NUMCPUS=`python2.7 -c 'import multiprocessing; print multiprocessing.cpu_count()'` - -make CONFIG=$config qps_worker qps_driver -j$NUMCPUS - -bins/$config/qps_worker -driver_port 10000 & -PID1=$! -bins/$config/qps_worker -driver_port 10010 & -PID2=$! - -export QPS_WORKERS="localhost:10000,localhost:10010" - -bins/$config/qps_driver $* - -kill -2 $PID1 $PID2 -wait - |