From 5c004c68deac80995cb3befcca441fc47cf9f302 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 23 Feb 2015 16:31:57 -0800 Subject: [PATCH 01/27] Driver changes WIP - things compile again after a broad set of changes preparing for the driver code. --- test/cpp/qps/client.cc | 177 +++++++++++++++++-------------------- test/cpp/qps/qpstest.proto | 46 +++++++--- test/cpp/qps/server.cc | 82 +++++++++++++---- 3 files changed, 178 insertions(+), 127 deletions(-) diff --git a/test/cpp/qps/client.cc b/test/cpp/qps/client.cc index 11c39eb4f52..213e5d92149 100644 --- a/test/cpp/qps/client.cc +++ b/test/cpp/qps/client.cc @@ -33,48 +33,36 @@ #include #include +#include #include #include #include #include +#include + #include +#include #include #include +#include #include #include #include +#include +#include #include "test/core/util/grpc_profiler.h" #include "test/cpp/util/create_test_channel.h" #include "test/cpp/qps/qpstest.pb.h" -DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls."); -DEFINE_int32(server_port, 0, "Server port."); -DEFINE_string(server_host, "127.0.0.1", "Server host."); -DEFINE_int32(client_threads, 4, "Number of client threads."); - -// We have a configurable number of channels for sending RPCs. -// RPCs are sent round-robin on the available channels by the -// various threads. Interesting cases are 1 global channel or -// 1 per-thread channel, but we can support any number. -// The channels are assigned round-robin on an RPC by RPC basis -// rather than just at initialization time in order to also measure the -// impact of cache thrashing caused by channel changes. This is an issue -// if you are not in one of the above "interesting cases" -DEFINE_int32(client_channels, 4, "Number of client channels."); - -DEFINE_int32(num_rpcs, 1000, "Number of RPCs per thread."); -DEFINE_int32(payload_size, 1, "Payload size in bytes"); - -// Alternatively, specify parameters for test as a workload so that multiple -// tests are initiated back-to-back. This is convenient for keeping a borg -// allocation consistent. This is a space-separated list of -// [threads channels num_rpcs payload_size ]* -DEFINE_string(workload, "", "Workload parameters"); +DEFINE_int32(driver_port, 0, "Client driver port."); using grpc::ChannelInterface; using grpc::CreateTestChannel; -using grpc::testing::ServerStats; +using grpc::ServerBuilder; +using grpc::testing::ClientArgs; +using grpc::testing::ClientResult; +using grpc::testing::QpsClient; using grpc::testing::SimpleRequest; using grpc::testing::SimpleResponse; using grpc::testing::StatsRequest; @@ -92,8 +80,11 @@ static double now() { return 1e9 * tv.tv_sec + tv.tv_nsec; } -void RunTest(const int client_threads, const int client_channels, - const int num_rpcs, const int payload_size) { +static bool got_sigint = false; + +static void sigint_handler(int x) { got_sigint = 1; } + +ClientResult RunTest(const ClientArgs& args) { gpr_log(GPR_INFO, "QPS test with parameters\n" "enable_ssl = %d\n" @@ -101,17 +92,14 @@ void RunTest(const int client_threads, const int client_channels, "client_threads = %d\n" "num_rpcs = %d\n" "payload_size = %d\n" - "server_host:server_port = %s:%d\n\n", - FLAGS_enable_ssl, client_channels, client_threads, num_rpcs, - payload_size, FLAGS_server_host.c_str(), FLAGS_server_port); - - std::ostringstream oss; - oss << FLAGS_server_host << ":" << FLAGS_server_port; + "server_target = %s\n\n", + args.enable_ssl(), args.client_channels(), args.client_threads(), args.num_rpcs(), + args.payload_size(), args.server_target().c_str()); class ClientChannelInfo { public: - explicit ClientChannelInfo(const grpc::string &server) - : channel_(CreateTestChannel(server, FLAGS_enable_ssl)), + explicit ClientChannelInfo(const ClientArgs& args) + : channel_(CreateTestChannel(args.server_target(), args.enable_ssl())), stub_(TestService::NewStub(channel_)) {} ChannelInterface *get_channel() { return channel_.get(); } TestService::Stub *get_stub() { return stub_.get(); } @@ -122,38 +110,33 @@ void RunTest(const int client_threads, const int client_channels, }; std::vector channels; - for (int i = 0; i < client_channels; i++) { - channels.push_back(ClientChannelInfo(oss.str())); + for (int i = 0; i < args.client_channels(); i++) { + channels.push_back(ClientChannelInfo(args)); } std::vector threads; // Will add threads when ready to execute - std::vector< ::gpr_histogram *> thread_stats(client_threads); + std::vector< ::gpr_histogram *> thread_stats(args.client_threads()); - TestService::Stub *stub_stats = channels[0].get_stub(); grpc::ClientContext context_stats_begin; - StatsRequest stats_request; - ServerStats server_stats_begin; - stats_request.set_test_num(0); - grpc::Status status_beg = stub_stats->CollectServerStats( - &context_stats_begin, stats_request, &server_stats_begin); grpc_profiler_start("qps_client.prof"); - for (int i = 0; i < client_threads; i++) { + gpr_timespec start = gpr_now(); + + for (int i = 0; i < args.client_threads(); i++) { gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); GPR_ASSERT(hist != NULL); thread_stats[i] = hist; threads.push_back( - std::thread([hist, client_threads, client_channels, num_rpcs, - payload_size, &channels](int channel_num) { + std::thread([hist, args, &channels](int channel_num) { SimpleRequest request; SimpleResponse response; request.set_response_type( grpc::testing::PayloadType::COMPRESSABLE); - request.set_response_size(payload_size); + request.set_response_size(args.payload_size()); - for (int j = 0; j < num_rpcs; j++) { + for (int j = 0; j < args.num_rpcs(); j++) { TestService::Stub *stub = channels[channel_num].get_stub(); double start = now(); @@ -166,26 +149,29 @@ void RunTest(const int client_threads, const int client_channels, (response.payload().type() == grpc::testing::PayloadType::COMPRESSABLE) && (response.payload().body().length() == - static_cast(payload_size))); + static_cast(args.payload_size()))); // Now do runtime round-robin assignment of the next // channel number - channel_num += client_threads; - channel_num %= client_channels; + channel_num += args.client_threads(); + channel_num %= args.client_channels(); } }, - i % client_channels)); + i % args.client_channels())); } - gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); - GPR_ASSERT(hist != NULL); for (auto &t : threads) { t.join(); } + gpr_timespec stop = gpr_now(); + grpc_profiler_stop(); - for (int i = 0; i < client_threads; i++) { + gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); + GPR_ASSERT(hist != NULL); + + for (int i = 0; i < args.client_threads(); i++) { gpr_histogram *h = thread_stats[i]; gpr_log(GPR_INFO, "latency at thread %d (50/90/95/99/99.9): %f/%f/%f/%f/%f", i, gpr_histogram_percentile(h, 50), gpr_histogram_percentile(h, 90), @@ -195,57 +181,54 @@ void RunTest(const int client_threads, const int client_channels, gpr_histogram_destroy(h); } - gpr_log( - GPR_INFO, - "latency across %d threads with %d channels and %d payload " - "(50/90/95/99/99.9): %f / %f / %f / %f / %f", - client_threads, client_channels, payload_size, - gpr_histogram_percentile(hist, 50), gpr_histogram_percentile(hist, 90), - gpr_histogram_percentile(hist, 95), gpr_histogram_percentile(hist, 99), - gpr_histogram_percentile(hist, 99.9)); + ClientResult result; + auto* latencies = result.mutable_latencies(); + latencies->set_l_50(gpr_histogram_percentile(hist, 50)); + latencies->set_l_90(gpr_histogram_percentile(hist, 90)); + latencies->set_l_99(gpr_histogram_percentile(hist, 99)); + latencies->set_l_999(gpr_histogram_percentile(hist, 99.9)); + gpr_timespec elapsed = gpr_time_sub(stop, start); + result.set_num_rpcs(args.client_threads() * args.num_rpcs()); + result.set_time_elapsed(elapsed.tv_sec + 1e-9 * elapsed.tv_nsec); + gpr_histogram_destroy(hist); - grpc::ClientContext context_stats_end; - ServerStats server_stats_end; - grpc::Status status_end = stub_stats->CollectServerStats( - &context_stats_end, stats_request, &server_stats_end); + return result; +} - double elapsed = server_stats_end.time_now() - server_stats_begin.time_now(); - int total_rpcs = client_threads * num_rpcs; - double utime = server_stats_end.time_user() - server_stats_begin.time_user(); - double stime = - server_stats_end.time_system() - server_stats_begin.time_system(); - gpr_log(GPR_INFO, - "Elapsed time: %.3f\n" - "RPC Count: %d\n" - "QPS: %.3f\n" - "System time: %.3f\n" - "User time: %.3f\n" - "Resource usage: %.1f%%\n", - elapsed, total_rpcs, total_rpcs / elapsed, stime, utime, - (stime + utime) / elapsed * 100.0); +class ClientImpl : public QpsClient::Service { + public: + + private: + std::mutex client_mu_; +}; + +static void RunServer() { + char* server_address = NULL; + gpr_join_host_port(&server_address, "::", FLAGS_driver_port); + + ClientImpl service; + + ServerBuilder builder; + builder.AddPort(server_address); + builder.RegisterService(&service); + + gpr_free(server_address); + + auto server = builder.BuildAndStart(); + + while (!got_sigint) { + std::this_thread::sleep_for(std::chrono::seconds(5)); + } } int main(int argc, char **argv) { grpc_init(); ParseCommandLineFlags(&argc, &argv, true); - GPR_ASSERT(FLAGS_server_port); - - if (FLAGS_workload.length() == 0) { - RunTest(FLAGS_client_threads, FLAGS_client_channels, FLAGS_num_rpcs, - FLAGS_payload_size); - } else { - std::istringstream workload(FLAGS_workload); - int client_threads, client_channels, num_rpcs, payload_size; - workload >> client_threads; - while (!workload.eof()) { - workload >> client_channels >> num_rpcs >> payload_size; - RunTest(client_threads, client_channels, num_rpcs, payload_size); - workload >> client_threads; - } - gpr_log(GPR_INFO, "Done with specified workload."); - } + signal(SIGINT, sigint_handler); + + RunServer(); grpc_shutdown(); return 0; diff --git a/test/cpp/qps/qpstest.proto b/test/cpp/qps/qpstest.proto index 68ec6149f59..fc589600176 100644 --- a/test/cpp/qps/qpstest.proto +++ b/test/cpp/qps/qpstest.proto @@ -78,17 +78,24 @@ message Latencies { required double l_999 = 4; } -message StartArgs { - required string server_host = 1; - required int32 server_port = 2; - optional bool enable_ssl = 3 [default = false]; - optional int32 client_threads = 4 [default = 1]; - optional int32 client_channels = 5 [default = -1]; - optional int32 num_rpcs = 6 [default = 1]; - optional int32 payload_size = 7 [default = 1]; +message ClientArgs { + required string server_target = 1; + required bool enable_ssl = 3; + required int32 client_threads = 4; + // We have a configurable number of channels for sending RPCs. + // RPCs are sent round-robin on the available channels by the + // various threads. Interesting cases are 1 global channel or + // 1 per-thread channel, but we can support any number. + // The channels are assigned round-robin on an RPC by RPC basis + // rather than just at initialization time in order to also measure the + // impact of cache thrashing caused by channel changes. This is an issue + // if you are not in one of the above "interesting cases" + required int32 client_channels = 5; + required int32 num_rpcs = 6; + required int32 payload_size = 7; } -message StartResult { +message ClientResult { required Latencies latencies = 1; required int32 num_rpcs = 2; required double time_elapsed = 3; @@ -96,6 +103,14 @@ message StartResult { required double time_system = 5; } +message ServerArgs { + required int32 threads = 1; +} + +message ServerStatus { + optional ServerStats stats = 1; +} + message SimpleRequest { // Desired payload type in the response from the server. // If response_type is RANDOM, server randomly chooses one from other formats. @@ -153,9 +168,6 @@ message StreamingOutputCallResponse { } service TestService { - // Start test with specified workload - rpc StartTest(StartArgs) returns (Latencies); - // Collect stats from server, ignore request content rpc CollectServerStats(StatsRequest) returns (ServerStats); @@ -186,3 +198,13 @@ service TestService { rpc HalfDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse); } + +service QpsClient { + // Start test with specified workload + rpc RunTest(ClientArgs) returns (ClientResult); +} + +service QpsServer { + // Start test with specified workload + rpc RunServer(stream ServerArgs) returns (stream ServerStatus); +} diff --git a/test/cpp/qps/server.cc b/test/cpp/qps/server.cc index 8e136349a15..a5edb054938 100644 --- a/test/cpp/qps/server.cc +++ b/test/cpp/qps/server.cc @@ -44,6 +44,7 @@ #include #include #include +#include #include "src/cpp/server/thread_pool.h" #include "test/core/util/grpc_profiler.h" #include "test/cpp/qps/qpstest.pb.h" @@ -51,13 +52,13 @@ #include #include -DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls."); DEFINE_int32(port, 0, "Server port."); -DEFINE_int32(server_threads, 4, "Number of server threads."); +DEFINE_int32(driver_port, 0, "Server driver port."); using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; +using grpc::ServerReaderWriter; using grpc::ThreadPool; using grpc::testing::Payload; using grpc::testing::PayloadType; @@ -66,6 +67,10 @@ using grpc::testing::SimpleRequest; using grpc::testing::SimpleResponse; using grpc::testing::StatsRequest; using grpc::testing::TestService; +using grpc::testing::QpsServer; +using grpc::testing::ServerArgs; +using grpc::testing::ServerStats; +using grpc::testing::ServerStatus; using grpc::Status; // In some distros, gflags is in the namespace google, and in some others, @@ -124,34 +129,76 @@ class TestServiceImpl final : public TestService::Service { } // namespace +class ServerImpl : public QpsServer::Service { + public: + Status RunServer(ServerContext* ctx, ServerReaderWriter* stream) { + ServerArgs args; + std::unique_ptr last_stats; + if (!stream->Read(&args)) return Status::OK; + + bool done = false; + while (!done) { + std::lock_guard lock(server_mu_); + + char* server_address = NULL; + gpr_join_host_port(&server_address, "::", FLAGS_port); + + TestServiceImpl service; + + ServerBuilder builder; + builder.AddPort(server_address); + builder.RegisterService(&service); + + gpr_free(server_address); + + std::unique_ptr pool(new ThreadPool(args.threads())); + builder.SetThreadPool(pool.get()); + + auto server = builder.BuildAndStart(); + gpr_log(GPR_INFO, "Server listening on %s\n", server_address); + + ServerStatus last_status; + if (last_stats.get()) { + *last_status.mutable_stats() = *last_stats; + } + if (!stream->Write(last_status)) return Status(grpc::UNKNOWN); + + grpc_profiler_start("qps_server.prof"); + + done = stream->Read(&args); + + grpc_profiler_stop(); + } + + ServerStatus last_status; + if (last_stats.get()) { + *last_status.mutable_stats() = *last_stats; + } + stream->Write(last_status); + return Status::OK; + } + + private: + std::mutex server_mu_; +}; + static void RunServer() { char* server_address = NULL; - gpr_join_host_port(&server_address, "::", FLAGS_port); - - TestServiceImpl service; + gpr_join_host_port(&server_address, "::", FLAGS_driver_port); - SimpleRequest request; - SimpleResponse response; + ServerImpl service; ServerBuilder builder; builder.AddPort(server_address); builder.RegisterService(&service); - std::unique_ptr pool(new ThreadPool(FLAGS_server_threads)); - builder.SetThreadPool(pool.get()); - - std::unique_ptr server(builder.BuildAndStart()); - gpr_log(GPR_INFO, "Server listening on %s\n", server_address); + gpr_free(server_address); - grpc_profiler_start("qps_server.prof"); + auto server = builder.BuildAndStart(); while (!got_sigint) { std::this_thread::sleep_for(std::chrono::seconds(5)); } - - grpc_profiler_stop(); - - gpr_free(server_address); } int main(int argc, char** argv) { @@ -161,7 +208,6 @@ int main(int argc, char** argv) { signal(SIGINT, sigint_handler); GPR_ASSERT(FLAGS_port != 0); - GPR_ASSERT(!FLAGS_enable_ssl); RunServer(); grpc_shutdown(); From e48601934d158f998e50bea19d301ffd8ae3d84f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 23 Feb 2015 17:10:41 -0800 Subject: [PATCH 02/27] Getting the driver pieces in place Driver logic not implemented yet --- Makefile | 111 ++++++++++++++++++++++++--- build.json | 31 +++++++- test/cpp/qps/driver.cc | 38 +++++++++ test/cpp/qps/driver.h | 42 ++++++++++ test/cpp/qps/qps_driver.cc | 63 +++++++++++++++ test/cpp/qps/single_run_localhost.sh | 26 +++++++ 6 files changed, 297 insertions(+), 14 deletions(-) create mode 100644 test/cpp/qps/driver.cc create mode 100644 test/cpp/qps/driver.h create mode 100644 test/cpp/qps/qps_driver.cc create mode 100755 test/cpp/qps/single_run_localhost.sh diff --git a/Makefile b/Makefile index b018febea10..86da127222e 100644 --- a/Makefile +++ b/Makefile @@ -522,6 +522,7 @@ pubsub_client: $(BINDIR)/$(CONFIG)/pubsub_client pubsub_publisher_test: $(BINDIR)/$(CONFIG)/pubsub_publisher_test pubsub_subscriber_test: $(BINDIR)/$(CONFIG)/pubsub_subscriber_test qps_client: $(BINDIR)/$(CONFIG)/qps_client +qps_driver: $(BINDIR)/$(CONFIG)/qps_driver qps_server: $(BINDIR)/$(CONFIG)/qps_server status_test: $(BINDIR)/$(CONFIG)/status_test thread_pool_test: $(BINDIR)/$(CONFIG)/thread_pool_test @@ -925,13 +926,13 @@ privatelibs: privatelibs_c privatelibs_cxx privatelibs_c: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fake_security.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_fullstack_uds.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_simple_ssl_with_oauth2_fullstack.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair.a $(LIBDIR)/$(CONFIG)/libend2end_fixture_chttp2_socket_pair_one_byte_at_a_time.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_before_invoke.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_in_a_vacuum.a $(LIBDIR)/$(CONFIG)/libend2end_test_census_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_disappearing_server.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags.a $(LIBDIR)/$(CONFIG)/libend2end_test_empty_batch.a $(LIBDIR)/$(CONFIG)/libend2end_test_graceful_server_shutdown.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_concurrent_streams.a $(LIBDIR)/$(CONFIG)/libend2end_test_no_op.a $(LIBDIR)/$(CONFIG)/libend2end_test_ping_pong_streaming.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_large_metadata.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_payload.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_delayed_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_request.a $(LIBDIR)/$(CONFIG)/libend2end_test_thread_stress.a $(LIBDIR)/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_accept_and_writes_closed_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_after_invoke_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_before_invoke_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_cancel_in_a_vacuum_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_census_simple_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_disappearing_server_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_inflight_calls_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_early_server_shutdown_finishes_tags_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_graceful_server_shutdown_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_invoke_large_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_max_concurrent_streams_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_no_op_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_ping_pong_streaming_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_binary_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_response_with_trailing_metadata_and_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_large_metadata_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_request_with_payload_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_delayed_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_simple_request_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_thread_stress_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_test_writes_done_hangs_with_pending_read_legacy.a $(LIBDIR)/$(CONFIG)/libend2end_certs.a -privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.a +privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.a $(LIBDIR)/$(CONFIG)/libqps.a buildtests: buildtests_c buildtests_cxx buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alarm_heap_test $(BINDIR)/$(CONFIG)/alarm_list_test $(BINDIR)/$(CONFIG)/alarm_test $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/census_hash_table_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test $(BINDIR)/$(CONFIG)/census_statistics_performance_test $(BINDIR)/$(CONFIG)/census_statistics_quick_test $(BINDIR)/$(CONFIG)/census_statistics_small_log_test $(BINDIR)/$(CONFIG)/census_stub_test $(BINDIR)/$(CONFIG)/census_window_stats_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/chttp2_transport_end2end_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/echo_client $(BINDIR)/$(CONFIG)/echo_server $(BINDIR)/$(CONFIG)/echo_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cancellable_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_stream_op_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/metadata_buffer_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/poll_kick_posix_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/time_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_legacy_test -buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/pubsub_client $(BINDIR)/$(CONFIG)/pubsub_publisher_test $(BINDIR)/$(CONFIG)/pubsub_subscriber_test $(BINDIR)/$(CONFIG)/qps_client $(BINDIR)/$(CONFIG)/qps_server $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/thread_pool_test +buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/pubsub_client $(BINDIR)/$(CONFIG)/pubsub_publisher_test $(BINDIR)/$(CONFIG)/pubsub_subscriber_test $(BINDIR)/$(CONFIG)/qps_client $(BINDIR)/$(CONFIG)/qps_driver $(BINDIR)/$(CONFIG)/qps_server $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/thread_pool_test test: test_c test_cxx @@ -3293,6 +3294,65 @@ $(OBJDIR)/$(CONFIG)/examples/pubsub/publisher.o: $(GENDIR)/examples/pubsub/l $(OBJDIR)/$(CONFIG)/examples/pubsub/subscriber.o: $(GENDIR)/examples/pubsub/label.pb.cc $(GENDIR)/examples/pubsub/empty.pb.cc $(GENDIR)/examples/pubsub/pubsub.pb.cc +LIBQPS_SRC = \ + $(GENDIR)/test/cpp/qps/qpstest.pb.cc \ + test/cpp/qps/driver.cc \ + + +LIBQPS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBQPS_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure libraries if you don't have OpenSSL with ALPN. + +$(LIBDIR)/$(CONFIG)/libqps.a: openssl_dep_error + + +else + +ifeq ($(NO_PROTOBUF),true) + +# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay. + +$(LIBDIR)/$(CONFIG)/libqps.a: protobuf_dep_error + + +else + +ifneq ($(OPENSSL_DEP),) +# This is to ensure the embedded OpenSSL is built beforehand, properly +# installing headers to their final destination on the drive. We need this +# otherwise parallel compilation will fail if a source is compiled first. +test/cpp/qps/qpstest.proto: $(OPENSSL_DEP) +test/cpp/qps/driver.cc: $(OPENSSL_DEP) +endif + +$(LIBDIR)/$(CONFIG)/libqps.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(PROTOBUF_DEP) $(LIBQPS_OBJS) + $(E) "[AR] Creating $@" + $(Q) mkdir -p `dirname $@` + $(Q) rm -f $(LIBDIR)/$(CONFIG)/libqps.a + $(Q) $(AR) rcs $(LIBDIR)/$(CONFIG)/libqps.a $(LIBQPS_OBJS) +ifeq ($(SYSTEM),Darwin) + $(Q) ranlib $(LIBDIR)/$(CONFIG)/libqps.a +endif + + + + +endif + +endif + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(LIBQPS_OBJS:.o=.dep) +endif +endif + + +$(OBJDIR)/$(CONFIG)/test/cpp/qps/driver.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc + + LIBGRPC_CSHARP_EXT_SRC = \ src/csharp/ext/grpc_csharp_ext.c \ @@ -7807,7 +7867,6 @@ endif QPS_CLIENT_SRC = \ - $(GENDIR)/test/cpp/qps/qpstest.pb.cc \ test/cpp/qps/client.cc \ QPS_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_CLIENT_SRC)))) @@ -7820,15 +7879,14 @@ $(BINDIR)/$(CONFIG)/qps_client: openssl_dep_error else -$(BINDIR)/$(CONFIG)/qps_client: $(QPS_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(BINDIR)/$(CONFIG)/qps_client: $(QPS_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(QPS_CLIENT_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_client + $(Q) $(LDXX) $(LDFLAGS) $(QPS_CLIENT_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_client endif -$(OBJDIR)/$(CONFIG)/test/cpp/qps/qpstest.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -$(OBJDIR)/$(CONFIG)/test/cpp/qps/client.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/qps/client.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_qps_client: $(QPS_CLIENT_OBJS:.o=.dep) @@ -7839,8 +7897,38 @@ endif endif +QPS_DRIVER_SRC = \ + test/cpp/qps/qps_driver.cc \ + +QPS_DRIVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_DRIVER_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +$(BINDIR)/$(CONFIG)/qps_driver: openssl_dep_error + +else + +$(BINDIR)/$(CONFIG)/qps_driver: $(QPS_DRIVER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(QPS_DRIVER_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_driver + +endif + +$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_driver.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_qps_driver: $(QPS_DRIVER_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(QPS_DRIVER_OBJS:.o=.dep) +endif +endif + + QPS_SERVER_SRC = \ - $(GENDIR)/test/cpp/qps/qpstest.pb.cc \ test/cpp/qps/server.cc \ QPS_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_SERVER_SRC)))) @@ -7853,15 +7941,14 @@ $(BINDIR)/$(CONFIG)/qps_server: openssl_dep_error else -$(BINDIR)/$(CONFIG)/qps_server: $(QPS_SERVER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(BINDIR)/$(CONFIG)/qps_server: $(QPS_SERVER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(QPS_SERVER_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_server + $(Q) $(LDXX) $(LDFLAGS) $(QPS_SERVER_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_server endif -$(OBJDIR)/$(CONFIG)/test/cpp/qps/qpstest.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -$(OBJDIR)/$(CONFIG)/test/cpp/qps/server.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/qps/server.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_qps_server: $(QPS_SERVER_OBJS:.o=.dep) diff --git a/build.json b/build.json index f6ef33b25fc..72afd53a7ea 100644 --- a/build.json +++ b/build.json @@ -468,6 +468,15 @@ "gpr" ] }, + { + "name": "qps", + "build": "private", + "language": "c++", + "src": [ + "test/cpp/qps/qpstest.proto", + "test/cpp/qps/driver.cc" + ] + }, { "name": "grpc_csharp_ext", "build": "all", @@ -1772,10 +1781,28 @@ "run": false, "language": "c++", "src": [ - "test/cpp/qps/qpstest.proto", "test/cpp/qps/client.cc" ], "deps": [ + "qps", + "grpc++_test_util", + "grpc_test_util", + "grpc++", + "grpc", + "gpr_test_util", + "gpr" + ] + }, + { + "name": "qps_driver", + "build": "test", + "run": false, + "language": "c++", + "src": [ + "test/cpp/qps/qps_driver.cc" + ], + "deps": [ + "qps", "grpc++_test_util", "grpc_test_util", "grpc++", @@ -1790,10 +1817,10 @@ "run": false, "language": "c++", "src": [ - "test/cpp/qps/qpstest.proto", "test/cpp/qps/server.cc" ], "deps": [ + "qps", "grpc++_test_util", "grpc_test_util", "grpc++", diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc new file mode 100644 index 00000000000..ed72e306028 --- /dev/null +++ b/test/cpp/qps/driver.cc @@ -0,0 +1,38 @@ +/* + * + * 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 "test/cpp/qps/driver.h" + +void RunScenario(const grpc::testing::ClientArgs& client_args, int num_clients, + const grpc::testing::ServerArgs& server_args, + int num_servers) {} diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h new file mode 100644 index 00000000000..6d6506d0490 --- /dev/null +++ b/test/cpp/qps/driver.h @@ -0,0 +1,42 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_DRIVER_H +#define TEST_QPS_DRIVER_H + +#include "test/cpp/qps/qpstest.pb.h" + +void RunScenario(const grpc::testing::ClientArgs& client_args, int num_clients, + const grpc::testing::ServerArgs& server_args, int num_servers); + +#endif diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc new file mode 100644 index 00000000000..e7dda8e8eec --- /dev/null +++ b/test/cpp/qps/qps_driver.cc @@ -0,0 +1,63 @@ +/* + * + * 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 + +#include "test/cpp/qps/driver.h" + +DEFINE_int32(num_clients, 1, "number of client binaries"); +DEFINE_int32(num_servers, 1, "number of server binaries"); + +using grpc::testing::ClientArgs; +using grpc::testing::ServerArgs; + +// In some distros, gflags is in the namespace google, and in some others, +// in gflags. This hack is enabling us to find both. +namespace google { } +namespace gflags { } +using namespace google; +using namespace gflags; + +int main(int argc, char **argv) { + grpc_init(); + ParseCommandLineFlags(&argc, &argv, true); + + ClientArgs client_args; + ServerArgs server_args; + + RunScenario(client_args, FLAGS_num_clients, server_args, FLAGS_num_servers); + + grpc_shutdown(); + return 0; +} + diff --git a/test/cpp/qps/single_run_localhost.sh b/test/cpp/qps/single_run_localhost.sh new file mode 100755 index 00000000000..1c2f1c85ebf --- /dev/null +++ b/test/cpp/qps/single_run_localhost.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# performs a single qps run with one client and one server + +set -ex + +cd $(dirname $0)/../../.. + +NUMCPUS=`python2.7 -c 'import multiprocessing; print multiprocessing.cpu_count()'` + +make CONFIG=opt qps_client qps_server qps_driver -j$NUMCPUS + +bins/opt/qps_server -driver_port 10000 -port 10002 & +SERVER_PID=$! +bins/opt/qps_client -driver_port 10001 & +CLIENT_PID=$! + +QPS_SERVERS=localhost:10000 +QPS_CLIENTS=localhost:10001 + +bins/opt/qps_driver $* + +kill -2 $CLIENT_PID +kill -2 $SERVER_PID +wait + From 4f7a1ff6ad06b946acb5a11c244af26bbe575d7a Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 23 Feb 2015 17:16:56 -0800 Subject: [PATCH 03/27] 'Fix' a race --- test/cpp/qps/single_run_localhost.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/cpp/qps/single_run_localhost.sh b/test/cpp/qps/single_run_localhost.sh index 1c2f1c85ebf..a0939a7e587 100755 --- a/test/cpp/qps/single_run_localhost.sh +++ b/test/cpp/qps/single_run_localhost.sh @@ -15,6 +15,9 @@ SERVER_PID=$! bins/opt/qps_client -driver_port 10001 & CLIENT_PID=$! +# wait for startup +sleep 2 + QPS_SERVERS=localhost:10000 QPS_CLIENTS=localhost:10001 From 4ef7a29f311165268cb77648805d616598eb3f57 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 23 Feb 2015 17:29:01 -0800 Subject: [PATCH 04/27] Create server/client lists --- test/cpp/qps/driver.cc | 35 ++++++++++++++++++++++++++-- test/cpp/qps/driver.h | 4 ++-- test/cpp/qps/single_run_localhost.sh | 4 ++-- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index ed72e306028..e7fc46b9e8c 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -32,7 +32,38 @@ */ #include "test/cpp/qps/driver.h" +#include "src/core/support/env.h" +#include +#include -void RunScenario(const grpc::testing::ClientArgs& client_args, int num_clients, +using std::vector; +using grpc::string; + +static vector get_hosts(const string& name) { + char* env = gpr_getenv(name.c_str()); + if (!env) return vector(); + + vector out; + char* p = env; + for (;;) { + char* comma = strchr(p, ','); + if (comma) { + out.emplace_back(p, comma); + p = comma + 1; + } else { + out.emplace_back(p); + gpr_free(env); + return out; + } + } +} + +void RunScenario(const grpc::testing::ClientArgs& client_args, size_t num_clients, const grpc::testing::ServerArgs& server_args, - int num_servers) {} + size_t num_servers) { + auto clients = get_hosts("QPS_CLIENTS"); + auto servers = get_hosts("QPS_SERVERS"); + + GPR_ASSERT(clients.size() >= num_clients); + GPR_ASSERT(servers.size() >= num_servers); +} diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h index 6d6506d0490..615e5b1b178 100644 --- a/test/cpp/qps/driver.h +++ b/test/cpp/qps/driver.h @@ -36,7 +36,7 @@ #include "test/cpp/qps/qpstest.pb.h" -void RunScenario(const grpc::testing::ClientArgs& client_args, int num_clients, - const grpc::testing::ServerArgs& server_args, int num_servers); +void RunScenario(const grpc::testing::ClientArgs& client_args, size_t num_clients, + const grpc::testing::ServerArgs& server_args, size_t num_servers); #endif diff --git a/test/cpp/qps/single_run_localhost.sh b/test/cpp/qps/single_run_localhost.sh index a0939a7e587..ef3e343ebde 100755 --- a/test/cpp/qps/single_run_localhost.sh +++ b/test/cpp/qps/single_run_localhost.sh @@ -18,8 +18,8 @@ CLIENT_PID=$! # wait for startup sleep 2 -QPS_SERVERS=localhost:10000 -QPS_CLIENTS=localhost:10001 +export QPS_SERVERS=localhost:10000 +export QPS_CLIENTS=localhost:10001 bins/opt/qps_driver $* From 2d0f36c84b50cce549ad76307cda56c4506f1a49 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 23 Feb 2015 23:16:17 -0800 Subject: [PATCH 05/27] Driver to client/server kind of works --- Makefile | 3 + build.json | 7 +- src/cpp/server/server.cc | 18 ++-- test/core/util/grpc_profiler.c | 2 +- test/cpp/qps/client.cc | 58 ++++++++----- test/cpp/qps/driver.cc | 125 ++++++++++++++++++++++++++- test/cpp/qps/driver.h | 4 +- test/cpp/qps/qps_driver.cc | 34 ++++++-- test/cpp/qps/qpstest.proto | 36 ++++---- test/cpp/qps/server.cc | 77 +++++++---------- test/cpp/qps/single_run_localhost.sh | 12 ++- test/cpp/qps/timer.cc | 65 ++++++++++++++ test/cpp/qps/timer.h | 55 ++++++++++++ 13 files changed, 381 insertions(+), 115 deletions(-) create mode 100644 test/cpp/qps/timer.cc create mode 100644 test/cpp/qps/timer.h diff --git a/Makefile b/Makefile index 609dc507c0a..dc27c2ac2e3 100644 --- a/Makefile +++ b/Makefile @@ -3307,6 +3307,7 @@ $(OBJDIR)/$(CONFIG)/examples/pubsub/subscriber.o: $(GENDIR)/examples/pubsub/ LIBQPS_SRC = \ $(GENDIR)/test/cpp/qps/qpstest.pb.cc \ test/cpp/qps/driver.cc \ + test/cpp/qps/timer.cc \ LIBQPS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBQPS_SRC)))) @@ -3335,6 +3336,7 @@ ifneq ($(OPENSSL_DEP),) # otherwise parallel compilation will fail if a source is compiled first. test/cpp/qps/qpstest.proto: $(OPENSSL_DEP) test/cpp/qps/driver.cc: $(OPENSSL_DEP) +test/cpp/qps/timer.cc: $(OPENSSL_DEP) endif $(LIBDIR)/$(CONFIG)/libqps.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(PROTOBUF_DEP) $(LIBQPS_OBJS) @@ -3361,6 +3363,7 @@ endif $(OBJDIR)/$(CONFIG)/test/cpp/qps/driver.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc +$(OBJDIR)/$(CONFIG)/test/cpp/qps/timer.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc LIBGRPC_CSHARP_EXT_SRC = \ diff --git a/build.json b/build.json index 3b6bc6ccdf6..9c357116bb9 100644 --- a/build.json +++ b/build.json @@ -475,9 +475,14 @@ "name": "qps", "build": "private", "language": "c++", + "headers": [ + "test/cpp/qps/driver.h", + "test/cpp/qps/timer.h" + ], "src": [ "test/cpp/qps/qpstest.proto", - "test/cpp/qps/driver.cc" + "test/cpp/qps/driver.cc", + "test/cpp/qps/timer.cc" ] }, { diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index f565d3aa5d5..f9c09fc09ab 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -265,17 +265,15 @@ bool Server::Start() { } void Server::Shutdown() { - { - std::unique_lock lock(mu_); - if (started_ && !shutdown_) { - shutdown_ = true; - grpc_server_shutdown(server_); - cq_.Shutdown(); + std::unique_lock lock(mu_); + if (started_ && !shutdown_) { + shutdown_ = true; + grpc_server_shutdown(server_); + cq_.Shutdown(); - // Wait for running callbacks to finish. - while (num_running_cb_ != 0) { - callback_cv_.wait(lock); - } + // Wait for running callbacks to finish. + while (num_running_cb_ != 0) { + callback_cv_.wait(lock); } } } diff --git a/test/core/util/grpc_profiler.c b/test/core/util/grpc_profiler.c index 35b9361c70c..d5b6cfeef10 100644 --- a/test/core/util/grpc_profiler.c +++ b/test/core/util/grpc_profiler.c @@ -44,7 +44,7 @@ void grpc_profiler_stop() { ProfilerStop(); } void grpc_profiler_start(const char *filename) { gpr_log(GPR_DEBUG, - "You do not have google-perftools installed, profiling is disabled"); + "You do not have google-perftools installed, profiling is disabled [for %s]", filename); gpr_log(GPR_DEBUG, "To install on ubuntu: sudo apt-get install google-perftools " "libgoogle-perftools-dev"); diff --git a/test/cpp/qps/client.cc b/test/cpp/qps/client.cc index 213e5d92149..214711e205b 100644 --- a/test/cpp/qps/client.cc +++ b/test/cpp/qps/client.cc @@ -54,13 +54,17 @@ #include "test/core/util/grpc_profiler.h" #include "test/cpp/util/create_test_channel.h" #include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/timer.h" DEFINE_int32(driver_port, 0, "Client driver port."); using grpc::ChannelInterface; using grpc::CreateTestChannel; using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::Status; using grpc::testing::ClientArgs; +using grpc::testing::ClientConfig; using grpc::testing::ClientResult; using grpc::testing::QpsClient; using grpc::testing::SimpleRequest; @@ -85,21 +89,22 @@ static bool got_sigint = false; static void sigint_handler(int x) { got_sigint = 1; } ClientResult RunTest(const ClientArgs& args) { + const auto& config = args.config(); + gpr_log(GPR_INFO, "QPS test with parameters\n" "enable_ssl = %d\n" "client_channels = %d\n" "client_threads = %d\n" "num_rpcs = %d\n" - "payload_size = %d\n" - "server_target = %s\n\n", - args.enable_ssl(), args.client_channels(), args.client_threads(), args.num_rpcs(), - args.payload_size(), args.server_target().c_str()); + "payload_size = %d\n", + config.enable_ssl(), config.client_channels(), config.client_threads(), config.num_rpcs(), + config.payload_size()); class ClientChannelInfo { public: - explicit ClientChannelInfo(const ClientArgs& args) - : channel_(CreateTestChannel(args.server_target(), args.enable_ssl())), + explicit ClientChannelInfo(const grpc::string& target, const ClientConfig& config) + : channel_(CreateTestChannel(target, config.enable_ssl())), stub_(TestService::NewStub(channel_)) {} ChannelInterface *get_channel() { return channel_.get(); } TestService::Stub *get_stub() { return stub_.get(); } @@ -110,33 +115,33 @@ ClientResult RunTest(const ClientArgs& args) { }; std::vector channels; - for (int i = 0; i < args.client_channels(); i++) { - channels.push_back(ClientChannelInfo(args)); + for (int i = 0; i < config.client_channels(); i++) { + channels.push_back(ClientChannelInfo(args.server_targets(i % args.server_targets_size()), config)); } std::vector threads; // Will add threads when ready to execute - std::vector< ::gpr_histogram *> thread_stats(args.client_threads()); + std::vector< ::gpr_histogram *> thread_stats(config.client_threads()); grpc::ClientContext context_stats_begin; grpc_profiler_start("qps_client.prof"); - gpr_timespec start = gpr_now(); + Timer timer; - for (int i = 0; i < args.client_threads(); i++) { + for (int i = 0; i < config.client_threads(); i++) { gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); GPR_ASSERT(hist != NULL); thread_stats[i] = hist; threads.push_back( - std::thread([hist, args, &channels](int channel_num) { + std::thread([hist, config, &channels](int channel_num) { SimpleRequest request; SimpleResponse response; request.set_response_type( grpc::testing::PayloadType::COMPRESSABLE); - request.set_response_size(args.payload_size()); + request.set_response_size(config.payload_size()); - for (int j = 0; j < args.num_rpcs(); j++) { + for (int j = 0; j < config.num_rpcs(); j++) { TestService::Stub *stub = channels[channel_num].get_stub(); double start = now(); @@ -149,29 +154,29 @@ ClientResult RunTest(const ClientArgs& args) { (response.payload().type() == grpc::testing::PayloadType::COMPRESSABLE) && (response.payload().body().length() == - static_cast(args.payload_size()))); + static_cast(config.payload_size()))); // Now do runtime round-robin assignment of the next // channel number - channel_num += args.client_threads(); - channel_num %= args.client_channels(); + channel_num += config.client_threads(); + channel_num %= config.client_channels(); } }, - i % args.client_channels())); + i % config.client_channels())); } for (auto &t : threads) { t.join(); } - gpr_timespec stop = gpr_now(); + auto timer_result = timer.Mark(); grpc_profiler_stop(); gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); GPR_ASSERT(hist != NULL); - for (int i = 0; i < args.client_threads(); i++) { + for (int i = 0; i < config.client_threads(); i++) { gpr_histogram *h = thread_stats[i]; gpr_log(GPR_INFO, "latency at thread %d (50/90/95/99/99.9): %f/%f/%f/%f/%f", i, gpr_histogram_percentile(h, 50), gpr_histogram_percentile(h, 90), @@ -187,17 +192,22 @@ ClientResult RunTest(const ClientArgs& args) { latencies->set_l_90(gpr_histogram_percentile(hist, 90)); latencies->set_l_99(gpr_histogram_percentile(hist, 99)); latencies->set_l_999(gpr_histogram_percentile(hist, 99.9)); - gpr_timespec elapsed = gpr_time_sub(stop, start); - result.set_num_rpcs(args.client_threads() * args.num_rpcs()); - result.set_time_elapsed(elapsed.tv_sec + 1e-9 * elapsed.tv_nsec); + result.set_num_rpcs(config.client_threads() * config.num_rpcs()); + result.set_time_elapsed(timer_result.wall); + result.set_time_system(timer_result.system); + result.set_time_user(timer_result.user); gpr_histogram_destroy(hist); return result; } -class ClientImpl : public QpsClient::Service { +class ClientImpl final : public QpsClient::Service { public: + Status RunTest(ServerContext* ctx, const ClientArgs* args, ClientResult* result) override { + *result = ::RunTest(*args); + return Status::OK; + } private: std::mutex client_mu_; diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index e7fc46b9e8c..098860610ca 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -35,9 +35,33 @@ #include "src/core/support/env.h" #include #include +#include +#include +#include +#include +#include +#include +#include +#include +using std::list; +using std::thread; +using std::unique_ptr; using std::vector; using grpc::string; +using grpc::ChannelArguments; +using grpc::ClientContext; +using grpc::ClientReaderWriter; +using grpc::CreateChannelDeprecated; +using grpc::Status; +using grpc::testing::ClientArgs; +using grpc::testing::ClientConfig; +using grpc::testing::ClientResult; +using grpc::testing::QpsClient; +using grpc::testing::QpsServer; +using grpc::testing::ServerArgs; +using grpc::testing::ServerConfig; +using grpc::testing::ServerStatus; static vector get_hosts(const string& name) { char* env = gpr_getenv(name.c_str()); @@ -58,12 +82,107 @@ static vector get_hosts(const string& name) { } } -void RunScenario(const grpc::testing::ClientArgs& client_args, size_t num_clients, - const grpc::testing::ServerArgs& server_args, - size_t num_servers) { +void RunScenario(const ClientConfig& client_config, size_t num_clients, + const ServerConfig& server_config, size_t num_servers) { + // ClientContext allocator (all are destroyed at scope exit) + list contexts; + auto alloc_context = [&contexts]() { + contexts.emplace_back(); + return &contexts.back(); + }; + + // Get client, server lists auto clients = get_hosts("QPS_CLIENTS"); auto servers = get_hosts("QPS_SERVERS"); GPR_ASSERT(clients.size() >= num_clients); GPR_ASSERT(servers.size() >= num_servers); + + // Trim to just what we need + clients.resize(num_clients); + servers.resize(num_servers); + + // Start servers + vector> server_stubs; + vector>> server_streams; + vector server_targets; + for (const auto& target : servers) { + server_stubs.push_back(QpsServer::NewStub(CreateChannelDeprecated(target, ChannelArguments()))); + auto* stub = server_stubs.back().get(); + ServerArgs args; + *args.mutable_config() = server_config; + server_streams.push_back(stub->RunServer(alloc_context())); + auto* stream = server_streams.back().get(); + if (!stream->Write(args)) { + gpr_log(GPR_ERROR, "Failed starting server"); + return; + } + ServerStatus init_status; + if (!stream->Read(&init_status)) { + gpr_log(GPR_ERROR, "Failed starting server"); + return; + } + char* host; + char* driver_port; + char* cli_target; + gpr_split_host_port(target.c_str(), &host, &driver_port); + gpr_join_host_port(&cli_target, host, init_status.port()); + server_targets.push_back(cli_target); + gpr_free(host); + gpr_free(driver_port); + gpr_free(cli_target); + } + + // Start clients + class Client { + public: + Client(ClientContext* ctx, const string& target, const ClientArgs& args) + : thread_([ctx, target, args, this]() { + auto stub = QpsClient::NewStub(CreateChannelDeprecated(target, ChannelArguments())); + status_ = stub->RunTest(ctx, args, &result_); + }) {} + + ~Client() { join(); } + + void join() { if (!joined_) { thread_.join(); joined_ = true; } } + + const Status& status() const { return status_; } + const ClientResult& result() const { return result_; } + + private: + bool joined_ = false; + Status status_; + ClientResult result_; + thread thread_; + }; + list running_clients; + size_t svr_idx = 0; + for (const auto& target : clients) { + ClientArgs args; + *args.mutable_config() = client_config; + for (size_t i = 0; i < num_servers; i++) { + args.add_server_targets(server_targets[svr_idx]); + svr_idx = (svr_idx + 1) % num_servers; + } + + running_clients.emplace_back(alloc_context(), target, args); + } + + // Finish clients + for (auto& client : running_clients) { + client.join(); + if (!client.status().IsOk()) { + gpr_log(GPR_ERROR, "Client failed"); + return; + } + } + + // Finish servers + for (auto& stream : server_streams) { + ServerStatus final_status; + ServerStatus dummy; + if (!stream->WritesDone() || !stream->Read(&final_status) || stream->Read(&dummy) || !stream->Finish().IsOk()) { + gpr_log(GPR_ERROR, "Server protocol error"); + } + } } diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h index 615e5b1b178..8ac9d2f0a3f 100644 --- a/test/cpp/qps/driver.h +++ b/test/cpp/qps/driver.h @@ -36,7 +36,7 @@ #include "test/cpp/qps/qpstest.pb.h" -void RunScenario(const grpc::testing::ClientArgs& client_args, size_t num_clients, - const grpc::testing::ServerArgs& server_args, size_t num_servers); +void RunScenario(const grpc::testing::ClientConfig& client_config, size_t num_clients, + const grpc::testing::ServerConfig& server_config, size_t num_servers); #endif diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc index e7dda8e8eec..88b9d373a11 100644 --- a/test/cpp/qps/qps_driver.cc +++ b/test/cpp/qps/qps_driver.cc @@ -35,11 +35,23 @@ #include "test/cpp/qps/driver.h" -DEFINE_int32(num_clients, 1, "number of client binaries"); -DEFINE_int32(num_servers, 1, "number of server binaries"); +DEFINE_int32(num_clients, 1, "Number of client binaries"); +DEFINE_int32(num_servers, 1, "Number of server binaries"); -using grpc::testing::ClientArgs; -using grpc::testing::ServerArgs; +// Common config +DEFINE_bool(enable_ssl, false, "Use SSL"); + +// Server config +DEFINE_int32(server_threads, 1, "Number of server threads"); + +// Client config +DEFINE_int32(client_threads, 1, "Number of client threads"); +DEFINE_int32(client_channels, 1, "Number of client channels"); +DEFINE_int32(num_rpcs, 10000, "Number of rpcs per client thread"); +DEFINE_int32(payload_size, 1, "Payload size"); + +using grpc::testing::ClientConfig; +using grpc::testing::ServerConfig; // In some distros, gflags is in the namespace google, and in some others, // in gflags. This hack is enabling us to find both. @@ -52,10 +64,18 @@ int main(int argc, char **argv) { grpc_init(); ParseCommandLineFlags(&argc, &argv, true); - ClientArgs client_args; - ServerArgs server_args; + ClientConfig client_config; + client_config.set_enable_ssl(FLAGS_enable_ssl); + client_config.set_client_threads(FLAGS_client_threads); + client_config.set_client_channels(FLAGS_client_channels); + client_config.set_num_rpcs(FLAGS_num_rpcs); + client_config.set_payload_size(FLAGS_payload_size); + + ServerConfig server_config; + server_config.set_threads(FLAGS_server_threads); + server_config.set_enable_ssl(FLAGS_enable_ssl); - RunScenario(client_args, FLAGS_num_clients, server_args, FLAGS_num_servers); + RunScenario(client_config, FLAGS_num_clients, server_config, FLAGS_num_servers); grpc_shutdown(); return 0; diff --git a/test/cpp/qps/qpstest.proto b/test/cpp/qps/qpstest.proto index fc589600176..11b7c882a62 100644 --- a/test/cpp/qps/qpstest.proto +++ b/test/cpp/qps/qpstest.proto @@ -51,17 +51,14 @@ message StatsRequest { } message ServerStats { - // wall clock time for timestamp - required double time_now = 1; + // wall clock time + required double time_elapsed = 1; // user time used by the server process and threads required double time_user = 2; // server time used by the server process and all threads required double time_system = 3; - - // RPC count so far - optional int32 num_rpcs = 4; } message Payload { @@ -78,10 +75,9 @@ message Latencies { required double l_999 = 4; } -message ClientArgs { - required string server_target = 1; - required bool enable_ssl = 3; - required int32 client_threads = 4; +message ClientConfig { + required bool enable_ssl = 1; + required int32 client_threads = 2; // We have a configurable number of channels for sending RPCs. // RPCs are sent round-robin on the available channels by the // various threads. Interesting cases are 1 global channel or @@ -90,9 +86,14 @@ message ClientArgs { // rather than just at initialization time in order to also measure the // impact of cache thrashing caused by channel changes. This is an issue // if you are not in one of the above "interesting cases" - required int32 client_channels = 5; - required int32 num_rpcs = 6; - required int32 payload_size = 7; + required int32 client_channels = 3; + required int32 num_rpcs = 4; + required int32 payload_size = 5; +} + +message ClientArgs { + repeated string server_targets = 1; + required ClientConfig config = 2; } message ClientResult { @@ -103,12 +104,18 @@ message ClientResult { required double time_system = 5; } -message ServerArgs { +message ServerConfig { required int32 threads = 1; + required bool enable_ssl = 2; +} + +message ServerArgs { + required ServerConfig config = 1; } message ServerStatus { optional ServerStats stats = 1; + required int32 port = 2; } message SimpleRequest { @@ -168,9 +175,6 @@ message StreamingOutputCallResponse { } service TestService { - // Collect stats from server, ignore request content - rpc CollectServerStats(StatsRequest) returns (ServerStats); - // One request followed by one response. // The server returns the client payload as-is. rpc UnaryCall(SimpleRequest) returns (SimpleResponse); diff --git a/test/cpp/qps/server.cc b/test/cpp/qps/server.cc index a5edb054938..89fdfeb0cb9 100644 --- a/test/cpp/qps/server.cc +++ b/test/cpp/qps/server.cc @@ -31,8 +31,6 @@ * */ -#include -#include #include #include @@ -48,6 +46,7 @@ #include "src/cpp/server/thread_pool.h" #include "test/core/util/grpc_profiler.h" #include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/timer.h" #include #include @@ -84,10 +83,6 @@ static bool got_sigint = false; static void sigint_handler(int x) { got_sigint = 1; } -static double time_double(struct timeval* tv) { - return tv->tv_sec + 1e-6 * tv->tv_usec; -} - static bool SetPayload(PayloadType type, int size, Payload* payload) { PayloadType response_type = type; // TODO(yangg): Support UNCOMPRESSABLE payload. @@ -104,19 +99,8 @@ namespace { class TestServiceImpl final : public TestService::Service { public: - Status CollectServerStats(ServerContext* context, const StatsRequest*, - ServerStats* response) { - struct rusage usage; - struct timeval tv; - gettimeofday(&tv, NULL); - getrusage(RUSAGE_SELF, &usage); - response->set_time_now(time_double(&tv)); - response->set_time_user(time_double(&usage.ru_utime)); - response->set_time_system(time_double(&usage.ru_stime)); - return Status::OK; - } Status UnaryCall(ServerContext* context, const SimpleRequest* request, - SimpleResponse* response) { + SimpleResponse* response) override { if (request->has_response_size() && request->response_size() > 0) { if (!SetPayload(request->response_type(), request->response_size(), response->mutable_payload())) { @@ -133,48 +117,47 @@ class ServerImpl : public QpsServer::Service { public: Status RunServer(ServerContext* ctx, ServerReaderWriter* stream) { ServerArgs args; - std::unique_ptr last_stats; if (!stream->Read(&args)) return Status::OK; - bool done = false; - while (!done) { - std::lock_guard lock(server_mu_); + std::lock_guard lock(server_mu_); - char* server_address = NULL; - gpr_join_host_port(&server_address, "::", FLAGS_port); + char* server_address = NULL; + gpr_join_host_port(&server_address, "::", FLAGS_port); - TestServiceImpl service; + TestServiceImpl service; - ServerBuilder builder; - builder.AddPort(server_address); - builder.RegisterService(&service); + ServerBuilder builder; + builder.AddPort(server_address); + builder.RegisterService(&service); - gpr_free(server_address); + std::unique_ptr pool(new ThreadPool(args.config().threads())); + builder.SetThreadPool(pool.get()); - std::unique_ptr pool(new ThreadPool(args.threads())); - builder.SetThreadPool(pool.get()); + auto server = builder.BuildAndStart(); + gpr_log(GPR_INFO, "Server listening on %s\n", server_address); - auto server = builder.BuildAndStart(); - gpr_log(GPR_INFO, "Server listening on %s\n", server_address); + gpr_free(server_address); - ServerStatus last_status; - if (last_stats.get()) { - *last_status.mutable_stats() = *last_stats; - } - if (!stream->Write(last_status)) return Status(grpc::UNKNOWN); - - grpc_profiler_start("qps_server.prof"); + ServerStatus status; + status.set_port(FLAGS_port); + if (!stream->Write(status)) return Status(grpc::UNKNOWN); - done = stream->Read(&args); + grpc_profiler_start("qps_server.prof"); + Timer timer; - grpc_profiler_stop(); + if (stream->Read(&args)) { + gpr_log(GPR_ERROR, "Got a server request, but not expecting one"); + return Status(grpc::UNKNOWN); } - ServerStatus last_status; - if (last_stats.get()) { - *last_status.mutable_stats() = *last_stats; - } - stream->Write(last_status); + auto timer_result = timer.Mark(); + grpc_profiler_stop(); + + auto* stats = status.mutable_stats(); + stats->set_time_elapsed(timer_result.wall); + stats->set_time_system(timer_result.system); + stats->set_time_user(timer_result.user); + stream->Write(status); return Status::OK; } diff --git a/test/cpp/qps/single_run_localhost.sh b/test/cpp/qps/single_run_localhost.sh index ef3e343ebde..317202a6abd 100755 --- a/test/cpp/qps/single_run_localhost.sh +++ b/test/cpp/qps/single_run_localhost.sh @@ -6,13 +6,17 @@ set -ex cd $(dirname $0)/../../.. +killall qps_server qps_client || true + +config=opt + NUMCPUS=`python2.7 -c 'import multiprocessing; print multiprocessing.cpu_count()'` -make CONFIG=opt qps_client qps_server qps_driver -j$NUMCPUS +make CONFIG=$config qps_client qps_server qps_driver -j$NUMCPUS -bins/opt/qps_server -driver_port 10000 -port 10002 & +bins/$config/qps_server -driver_port 10000 -port 10002 & SERVER_PID=$! -bins/opt/qps_client -driver_port 10001 & +bins/$config/qps_client -driver_port 10001 & CLIENT_PID=$! # wait for startup @@ -21,7 +25,7 @@ sleep 2 export QPS_SERVERS=localhost:10000 export QPS_CLIENTS=localhost:10001 -bins/opt/qps_driver $* +bins/$config/qps_driver $* kill -2 $CLIENT_PID kill -2 $SERVER_PID diff --git a/test/cpp/qps/timer.cc b/test/cpp/qps/timer.cc new file mode 100644 index 00000000000..ff21f1a3778 --- /dev/null +++ b/test/cpp/qps/timer.cc @@ -0,0 +1,65 @@ +/* + * + * 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 "test/cpp/qps/timer.h" + +#include +#include + +Timer::Timer() : start_(Sample()) {} + +static double time_double(struct timeval* tv) { + return tv->tv_sec + 1e-6 * tv->tv_usec; +} + +Timer::Result Timer::Sample() { + struct rusage usage; + struct timeval tv; + gettimeofday(&tv, NULL); + getrusage(RUSAGE_SELF, &usage); + + Result r; + r.wall = time_double(&tv); + r.user = time_double(&usage.ru_utime); + r.system = time_double(&usage.ru_stime); + return r; +} + +Timer::Result Timer::Mark() { + Result s = Sample(); + Result r; + r.wall = s.wall - start_.wall; + r.user = s.user - start_.user; + r.system = s.system - start_.system; + return r; +} \ No newline at end of file diff --git a/test/cpp/qps/timer.h b/test/cpp/qps/timer.h new file mode 100644 index 00000000000..8a229cbd305 --- /dev/null +++ b/test/cpp/qps/timer.h @@ -0,0 +1,55 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_TIMER_H +#define TEST_QPS_TIMER_H + +class Timer { + public: + Timer(); + + struct Result { + double wall; + double user; + double system; + }; + + Result Mark(); + + private: + static Result Sample(); + + const Result start_; +}; + +#endif // TEST_QPS_TIMER_H From 2f3fa9acff3eb7cacbb590446eb9d5546a8a43ca Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 24 Feb 2015 17:04:22 -0800 Subject: [PATCH 06/27] Fix linux compile bug --- test/cpp/qps/timer.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cpp/qps/timer.cc b/test/cpp/qps/timer.cc index ff21f1a3778..5a5be97071b 100644 --- a/test/cpp/qps/timer.cc +++ b/test/cpp/qps/timer.cc @@ -45,7 +45,7 @@ static double time_double(struct timeval* tv) { Timer::Result Timer::Sample() { struct rusage usage; struct timeval tv; - gettimeofday(&tv, NULL); + gettimeofday(&tv, nullptr); getrusage(RUSAGE_SELF, &usage); Result r; @@ -62,4 +62,4 @@ Timer::Result Timer::Mark() { r.user = s.user - start_.user; r.system = s.system - start_.system; return r; -} \ No newline at end of file +} From 8ecb170151e061f35d3799885ba63b5762f2057e Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 24 Feb 2015 17:08:23 -0800 Subject: [PATCH 07/27] Fix that race better --- test/cpp/qps/client.cc | 4 ++-- test/cpp/qps/server.cc | 4 ++-- test/cpp/qps/single_run_localhost.sh | 3 --- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/test/cpp/qps/client.cc b/test/cpp/qps/client.cc index 214711e205b..7c9763a332d 100644 --- a/test/cpp/qps/client.cc +++ b/test/cpp/qps/client.cc @@ -233,11 +233,11 @@ static void RunServer() { } int main(int argc, char **argv) { + signal(SIGINT, sigint_handler); + grpc_init(); ParseCommandLineFlags(&argc, &argv, true); - signal(SIGINT, sigint_handler); - RunServer(); grpc_shutdown(); diff --git a/test/cpp/qps/server.cc b/test/cpp/qps/server.cc index 89fdfeb0cb9..7d9a9d1d28e 100644 --- a/test/cpp/qps/server.cc +++ b/test/cpp/qps/server.cc @@ -185,11 +185,11 @@ static void RunServer() { } int main(int argc, char** argv) { + signal(SIGINT, sigint_handler); + grpc_init(); ParseCommandLineFlags(&argc, &argv, true); - signal(SIGINT, sigint_handler); - GPR_ASSERT(FLAGS_port != 0); RunServer(); diff --git a/test/cpp/qps/single_run_localhost.sh b/test/cpp/qps/single_run_localhost.sh index 317202a6abd..310a0824bb3 100755 --- a/test/cpp/qps/single_run_localhost.sh +++ b/test/cpp/qps/single_run_localhost.sh @@ -19,9 +19,6 @@ SERVER_PID=$! bins/$config/qps_client -driver_port 10001 & CLIENT_PID=$! -# wait for startup -sleep 2 - export QPS_SERVERS=localhost:10000 export QPS_CLIENTS=localhost:10001 From b449de0bb45b3acd59d8ddfaaa077c451d56a9f4 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Mar 2015 09:18:05 -0800 Subject: [PATCH 08/27] Cleaned --- build.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build.json b/build.json index f97ff687e31..590d6f8c8e5 100644 --- a/build.json +++ b/build.json @@ -1834,15 +1834,15 @@ ] }, { - "name": "qps_driver", + "name": "qps_client_async", "build": "test", "run": false, "language": "c++", "src": [ - "test/cpp/qps/qps_driver.cc" + "test/cpp/qps/qpstest.proto", + "test/cpp/qps/client_async.cc" ], "deps": [ - "qps", "grpc++_test_util", "grpc_test_util", "grpc++", @@ -1852,15 +1852,15 @@ ] }, { - "name": "qps_client_async", + "name": "qps_driver", "build": "test", "run": false, "language": "c++", "src": [ - "test/cpp/qps/qpstest.proto", - "test/cpp/qps/client_async.cc" + "test/cpp/qps/qps_driver.cc" ], "deps": [ + "qps", "grpc++_test_util", "grpc_test_util", "grpc++", From 26598a394a74bb89614b68428f5cdd3cb1279663 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Mar 2015 16:16:00 -0800 Subject: [PATCH 09/27] WIP --- Makefile | 157 +++------------------------- build.json | 64 ++---------- test/cpp/qps/client.h | 53 ++++++++++ test/cpp/qps/driver.cc | 8 +- test/cpp/qps/qpstest.proto | 46 ++++++--- test/cpp/qps/server.h | 53 ++++++++++ test/cpp/qps/worker.cc | 202 +++++++++++++++++++++++++++++++++++++ 7 files changed, 366 insertions(+), 217 deletions(-) create mode 100644 test/cpp/qps/client.h create mode 100644 test/cpp/qps/server.h create mode 100644 test/cpp/qps/worker.cc diff --git a/Makefile b/Makefile index 840fb55e6a0..bb65da78625 100644 --- a/Makefile +++ b/Makefile @@ -544,11 +544,8 @@ interop_test: $(BINDIR)/$(CONFIG)/interop_test pubsub_client: $(BINDIR)/$(CONFIG)/pubsub_client pubsub_publisher_test: $(BINDIR)/$(CONFIG)/pubsub_publisher_test pubsub_subscriber_test: $(BINDIR)/$(CONFIG)/pubsub_subscriber_test -qps_client: $(BINDIR)/$(CONFIG)/qps_client -qps_client_async: $(BINDIR)/$(CONFIG)/qps_client_async qps_driver: $(BINDIR)/$(CONFIG)/qps_driver -qps_server: $(BINDIR)/$(CONFIG)/qps_server -qps_server_async: $(BINDIR)/$(CONFIG)/qps_server_async +qps_worker: $(BINDIR)/$(CONFIG)/qps_worker status_test: $(BINDIR)/$(CONFIG)/status_test thread_pool_test: $(BINDIR)/$(CONFIG)/thread_pool_test chttp2_fake_security_cancel_after_accept_test: $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test @@ -961,7 +958,7 @@ buildtests: buildtests_c buildtests_cxx buildtests_c: privatelibs_c $(BINDIR)/$(CONFIG)/alarm_heap_test $(BINDIR)/$(CONFIG)/alarm_list_test $(BINDIR)/$(CONFIG)/alarm_test $(BINDIR)/$(CONFIG)/alpn_test $(BINDIR)/$(CONFIG)/bin_encoder_test $(BINDIR)/$(CONFIG)/census_hash_table_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test $(BINDIR)/$(CONFIG)/census_statistics_multiple_writers_test $(BINDIR)/$(CONFIG)/census_statistics_performance_test $(BINDIR)/$(CONFIG)/census_statistics_quick_test $(BINDIR)/$(CONFIG)/census_statistics_small_log_test $(BINDIR)/$(CONFIG)/census_stub_test $(BINDIR)/$(CONFIG)/census_window_stats_test $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test $(BINDIR)/$(CONFIG)/chttp2_stream_encoder_test $(BINDIR)/$(CONFIG)/chttp2_stream_map_test $(BINDIR)/$(CONFIG)/chttp2_transport_end2end_test $(BINDIR)/$(CONFIG)/dualstack_socket_test $(BINDIR)/$(CONFIG)/echo_client $(BINDIR)/$(CONFIG)/echo_server $(BINDIR)/$(CONFIG)/echo_test $(BINDIR)/$(CONFIG)/fd_posix_test $(BINDIR)/$(CONFIG)/fling_client $(BINDIR)/$(CONFIG)/fling_server $(BINDIR)/$(CONFIG)/fling_stream_test $(BINDIR)/$(CONFIG)/fling_test $(BINDIR)/$(CONFIG)/gpr_cancellable_test $(BINDIR)/$(CONFIG)/gpr_cmdline_test $(BINDIR)/$(CONFIG)/gpr_env_test $(BINDIR)/$(CONFIG)/gpr_file_test $(BINDIR)/$(CONFIG)/gpr_histogram_test $(BINDIR)/$(CONFIG)/gpr_host_port_test $(BINDIR)/$(CONFIG)/gpr_log_test $(BINDIR)/$(CONFIG)/gpr_slice_buffer_test $(BINDIR)/$(CONFIG)/gpr_slice_test $(BINDIR)/$(CONFIG)/gpr_string_test $(BINDIR)/$(CONFIG)/gpr_sync_test $(BINDIR)/$(CONFIG)/gpr_thd_test $(BINDIR)/$(CONFIG)/gpr_time_test $(BINDIR)/$(CONFIG)/gpr_useful_test $(BINDIR)/$(CONFIG)/grpc_base64_test $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test $(BINDIR)/$(CONFIG)/grpc_channel_stack_test $(BINDIR)/$(CONFIG)/grpc_completion_queue_test $(BINDIR)/$(CONFIG)/grpc_credentials_test $(BINDIR)/$(CONFIG)/grpc_json_token_test $(BINDIR)/$(CONFIG)/grpc_stream_op_test $(BINDIR)/$(CONFIG)/hpack_parser_test $(BINDIR)/$(CONFIG)/hpack_table_test $(BINDIR)/$(CONFIG)/httpcli_format_request_test $(BINDIR)/$(CONFIG)/httpcli_parser_test $(BINDIR)/$(CONFIG)/httpcli_test $(BINDIR)/$(CONFIG)/json_rewrite $(BINDIR)/$(CONFIG)/json_rewrite_test $(BINDIR)/$(CONFIG)/json_test $(BINDIR)/$(CONFIG)/lame_client_test $(BINDIR)/$(CONFIG)/message_compress_test $(BINDIR)/$(CONFIG)/metadata_buffer_test $(BINDIR)/$(CONFIG)/multi_init_test $(BINDIR)/$(CONFIG)/murmur_hash_test $(BINDIR)/$(CONFIG)/no_server_test $(BINDIR)/$(CONFIG)/poll_kick_posix_test $(BINDIR)/$(CONFIG)/resolve_address_test $(BINDIR)/$(CONFIG)/secure_endpoint_test $(BINDIR)/$(CONFIG)/sockaddr_utils_test $(BINDIR)/$(CONFIG)/tcp_client_posix_test $(BINDIR)/$(CONFIG)/tcp_posix_test $(BINDIR)/$(CONFIG)/tcp_server_posix_test $(BINDIR)/$(CONFIG)/time_averaged_stats_test $(BINDIR)/$(CONFIG)/time_test $(BINDIR)/$(CONFIG)/timeout_encoding_test $(BINDIR)/$(CONFIG)/transport_metadata_test $(BINDIR)/$(CONFIG)/transport_security_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_fullstack_uds_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_empty_batch_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_large_metadata_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_with_payload_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_legacy_test $(BINDIR)/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_legacy_test -buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/pubsub_client $(BINDIR)/$(CONFIG)/pubsub_publisher_test $(BINDIR)/$(CONFIG)/pubsub_subscriber_test $(BINDIR)/$(CONFIG)/qps_client $(BINDIR)/$(CONFIG)/qps_client_async $(BINDIR)/$(CONFIG)/qps_driver $(BINDIR)/$(CONFIG)/qps_server $(BINDIR)/$(CONFIG)/qps_server_async $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/thread_pool_test +buildtests_cxx: privatelibs_cxx $(BINDIR)/$(CONFIG)/async_end2end_test $(BINDIR)/$(CONFIG)/channel_arguments_test $(BINDIR)/$(CONFIG)/credentials_test $(BINDIR)/$(CONFIG)/end2end_test $(BINDIR)/$(CONFIG)/interop_client $(BINDIR)/$(CONFIG)/interop_server $(BINDIR)/$(CONFIG)/interop_test $(BINDIR)/$(CONFIG)/pubsub_client $(BINDIR)/$(CONFIG)/pubsub_publisher_test $(BINDIR)/$(CONFIG)/pubsub_subscriber_test $(BINDIR)/$(CONFIG)/qps_driver $(BINDIR)/$(CONFIG)/qps_worker $(BINDIR)/$(CONFIG)/status_test $(BINDIR)/$(CONFIG)/thread_pool_test test: test_c test_cxx @@ -8081,92 +8078,6 @@ endif endif -QPS_CLIENT_SRC = \ - test/cpp/qps/client.cc \ - -QPS_CLIENT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_CLIENT_SRC)))) - -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/qps_client: openssl_dep_error - -else - - -ifeq ($(NO_PROTOBUF),true) - -# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. - -$(BINDIR)/$(CONFIG)/qps_client: protobuf_dep_error - -else - -$(BINDIR)/$(CONFIG)/qps_client: $(PROTOBUF_DEP) $(QPS_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(QPS_CLIENT_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_client - -endif - -endif - -$(OBJDIR)/$(CONFIG)/test/cpp/qps/client.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - -deps_qps_client: $(QPS_CLIENT_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(QPS_CLIENT_OBJS:.o=.dep) -endif -endif - - -QPS_CLIENT_ASYNC_SRC = \ - $(GENDIR)/test/cpp/qps/qpstest.pb.cc \ - test/cpp/qps/client_async.cc \ - -QPS_CLIENT_ASYNC_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_CLIENT_ASYNC_SRC)))) - -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/qps_client_async: openssl_dep_error - -else - - -ifeq ($(NO_PROTOBUF),true) - -# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. - -$(BINDIR)/$(CONFIG)/qps_client_async: protobuf_dep_error - -else - -$(BINDIR)/$(CONFIG)/qps_client_async: $(PROTOBUF_DEP) $(QPS_CLIENT_ASYNC_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(QPS_CLIENT_ASYNC_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_client_async - -endif - -endif - -$(OBJDIR)/$(CONFIG)/test/cpp/qps/qpstest.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - -deps_qps_client_async: $(QPS_CLIENT_ASYNC_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(QPS_CLIENT_ASYNC_OBJS:.o=.dep) -endif -endif - - QPS_DRIVER_SRC = \ test/cpp/qps/qps_driver.cc \ @@ -8209,16 +8120,18 @@ endif endif -QPS_SERVER_SRC = \ +QPS_WORKER_SRC = \ + test/cpp/qps/client.cc \ test/cpp/qps/server.cc \ + test/cpp/qps/worker.cc \ -QPS_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_SERVER_SRC)))) +QPS_WORKER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_WORKER_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL with ALPN. -$(BINDIR)/$(CONFIG)/qps_server: openssl_dep_error +$(BINDIR)/$(CONFIG)/qps_worker: openssl_dep_error else @@ -8227,70 +8140,28 @@ ifeq ($(NO_PROTOBUF),true) # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. -$(BINDIR)/$(CONFIG)/qps_server: protobuf_dep_error +$(BINDIR)/$(CONFIG)/qps_worker: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/qps_server: $(PROTOBUF_DEP) $(QPS_SERVER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(BINDIR)/$(CONFIG)/qps_worker: $(PROTOBUF_DEP) $(QPS_WORKER_OBJS) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(QPS_SERVER_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_server + $(Q) $(LDXX) $(LDFLAGS) $(QPS_WORKER_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_worker endif endif +$(OBJDIR)/$(CONFIG)/test/cpp/qps/client.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/qps/server.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/qps/worker.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_qps_server: $(QPS_SERVER_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(QPS_SERVER_OBJS:.o=.dep) -endif -endif - - -QPS_SERVER_ASYNC_SRC = \ - $(GENDIR)/test/cpp/qps/qpstest.pb.cc \ - test/cpp/qps/server_async.cc \ - -QPS_SERVER_ASYNC_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_SERVER_ASYNC_SRC)))) - -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -$(BINDIR)/$(CONFIG)/qps_server_async: openssl_dep_error - -else - - -ifeq ($(NO_PROTOBUF),true) - -# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. - -$(BINDIR)/$(CONFIG)/qps_server_async: protobuf_dep_error - -else - -$(BINDIR)/$(CONFIG)/qps_server_async: $(PROTOBUF_DEP) $(QPS_SERVER_ASYNC_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(QPS_SERVER_ASYNC_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/qps_server_async - -endif - -endif - -$(OBJDIR)/$(CONFIG)/test/cpp/qps/qpstest.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a - -deps_qps_server_async: $(QPS_SERVER_ASYNC_OBJS:.o=.dep) +deps_qps_worker: $(QPS_WORKER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) --include $(QPS_SERVER_ASYNC_OBJS:.o=.dep) +-include $(QPS_WORKER_OBJS:.o=.dep) endif endif diff --git a/build.json b/build.json index 590d6f8c8e5..a48491ba5a6 100644 --- a/build.json +++ b/build.json @@ -1815,42 +1815,6 @@ "gpr" ] }, - { - "name": "qps_client", - "build": "test", - "run": false, - "language": "c++", - "src": [ - "test/cpp/qps/client.cc" - ], - "deps": [ - "qps", - "grpc++_test_util", - "grpc_test_util", - "grpc++", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "qps_client_async", - "build": "test", - "run": false, - "language": "c++", - "src": [ - "test/cpp/qps/qpstest.proto", - "test/cpp/qps/client_async.cc" - ], - "deps": [ - "grpc++_test_util", - "grpc_test_util", - "grpc++", - "grpc", - "gpr_test_util", - "gpr" - ] - }, { "name": "qps_driver", "build": "test", @@ -1870,33 +1834,21 @@ ] }, { - "name": "qps_server", + "name": "qps_worker", "build": "test", "run": false, "language": "c++", - "src": [ - "test/cpp/qps/server.cc" + "headers": [ + "test/cpp/qps/client.h", + "test/cpp/qps/server.h" ], - "deps": [ - "qps", - "grpc++_test_util", - "grpc_test_util", - "grpc++", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "qps_server_async", - "build": "test", - "run": false, - "language": "c++", "src": [ - "test/cpp/qps/qpstest.proto", - "test/cpp/qps/server_async.cc" + "test/cpp/qps/client.cc", + "test/cpp/qps/server.cc", + "test/cpp/qps/worker.cc" ], "deps": [ + "qps", "grpc++_test_util", "grpc_test_util", "grpc++", diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h new file mode 100644 index 00000000000..ab34970ebd3 --- /dev/null +++ b/test/cpp/qps/client.h @@ -0,0 +1,53 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_CLIENT_H +#define TEST_QPS_CLIENT_H + +#include "test/cpp/qps/qpstest.pb.h" + +namespace grpc { +namespace testing { + +class Client { + public: + virtual ~Client() {} +}; + +std::unique_ptr CreateSynchronousClient(const ClientConfig& args); +std::unique_ptr CreateAsyncClient(const ClientConfig& args); + +} // namespace testing +} // namespace grpc + +#endif diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index 098860610ca..a54aad5631f 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -57,12 +57,12 @@ using grpc::Status; using grpc::testing::ClientArgs; using grpc::testing::ClientConfig; using grpc::testing::ClientResult; -using grpc::testing::QpsClient; -using grpc::testing::QpsServer; +using grpc::testing::Worker; using grpc::testing::ServerArgs; using grpc::testing::ServerConfig; using grpc::testing::ServerStatus; +#if 0 static vector get_hosts(const string& name) { char* env = gpr_getenv(name.c_str()); if (!env) return vector(); @@ -92,8 +92,7 @@ void RunScenario(const ClientConfig& client_config, size_t num_clients, }; // Get client, server lists - auto clients = get_hosts("QPS_CLIENTS"); - auto servers = get_hosts("QPS_SERVERS"); + auto workers = get_hosts("QPS_WORKERS"); GPR_ASSERT(clients.size() >= num_clients); GPR_ASSERT(servers.size() >= num_servers); @@ -186,3 +185,4 @@ void RunScenario(const ClientConfig& client_config, size_t num_clients, } } } +#endif \ No newline at end of file diff --git a/test/cpp/qps/qpstest.proto b/test/cpp/qps/qpstest.proto index 11b7c882a62..52d79579446 100644 --- a/test/cpp/qps/qpstest.proto +++ b/test/cpp/qps/qpstest.proto @@ -75,9 +75,21 @@ message Latencies { required double l_999 = 4; } +enum ClientType { + SYNCHRONOUS_CLIENT = 1; + ASYNC_CLIENT = 2; +} + +enum ServerType { + SYNCHRONOUS_SERVER = 1; + ASYNC_SERVER = 2; +} + message ClientConfig { - required bool enable_ssl = 1; - required int32 client_threads = 2; + repeated string server_targets = 1; + required ClientType client_type = 2; + required bool enable_ssl = 3; + required int32 client_threads = 4; // We have a configurable number of channels for sending RPCs. // RPCs are sent round-robin on the available channels by the // various threads. Interesting cases are 1 global channel or @@ -86,14 +98,18 @@ message ClientConfig { // rather than just at initialization time in order to also measure the // impact of cache thrashing caused by channel changes. This is an issue // if you are not in one of the above "interesting cases" - required int32 client_channels = 3; - required int32 num_rpcs = 4; - required int32 payload_size = 5; + required int32 client_channels = 5; + required int32 num_rpcs = 6; + required int32 payload_size = 7; } +message ClientStart {} + message ClientArgs { - repeated string server_targets = 1; - required ClientConfig config = 2; + oneof argtype { + ClientConfig setup = 1; + ClientStart start = 2; + } } message ClientResult { @@ -104,9 +120,14 @@ message ClientResult { required double time_system = 5; } +message ClientStatus { + optional ClientResult result = 1; +} + message ServerConfig { - required int32 threads = 1; - required bool enable_ssl = 2; + required ServerType server_type = 1; + required int32 threads = 2; + required bool enable_ssl = 3; } message ServerArgs { @@ -203,12 +224,9 @@ service TestService { returns (stream StreamingOutputCallResponse); } -service QpsClient { +service Worker { // Start test with specified workload - rpc RunTest(ClientArgs) returns (ClientResult); -} - -service QpsServer { + rpc RunTest(stream ClientArgs) returns (stream ClientStatus); // Start test with specified workload rpc RunServer(stream ServerArgs) returns (stream ServerStatus); } diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h new file mode 100644 index 00000000000..25c15e4d0cc --- /dev/null +++ b/test/cpp/qps/server.h @@ -0,0 +1,53 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_SERVER_H +#define TEST_QPS_SERVER_H + +#include "test/cpp/qps/qpstest.pb.h" + +namespace grpc { +namespace testing { + +class Server { + public: + virtual ~Server() {} +}; + +std::unique_ptr CreateSynchronousServer(const ServerConfig& config, int port); +std::unique_ptr CreateAsyncServer(const ServerConfig& config, int port); + +} // namespace testing +} // namespace grpc + +#endif diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc new file mode 100644 index 00000000000..749420bd694 --- /dev/null +++ b/test/cpp/qps/worker.cc @@ -0,0 +1,202 @@ +/* + * + * 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 +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/core/util/grpc_profiler.h" +#include "test/cpp/util/create_test_channel.h" +#include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/client.h" +#include "test/cpp/qps/server.h" + +DEFINE_int32(driver_port, 0, "Driver server port."); +DEFINE_int32(server_port, 0, "Spawned server port."); + +// In some distros, gflags is in the namespace google, and in some others, +// in gflags. This hack is enabling us to find both. +namespace google { } +namespace gflags { } +using namespace google; +using namespace gflags; + +static bool got_sigint = false; + +static void sigint_handler(int x) { got_sigint = 1; } + +namespace grpc { +namespace testing { + +std::unique_ptr CreateClient(const ClientConfig& config) { + switch (config.client_type()) { + case ClientType::SYNCHRONOUS_CLIENT: return CreateSynchronousClient(config); + case ClientType::ASYNC_CLIENT: return CreateAsyncClient(config); + } + abort(); +} + +std::unique_ptr CreateServer(const ServerConfig& config) { + switch (config.server_type()) { + case ServerType::SYNCHRONOUS_SERVER: return CreateSynchronousServer(config, FLAGS_server_port); + case ServerType::ASYNC_SERVER: return CreateAsyncServer(config, FLAGS_server_port); + } + abort(); +} + +class WorkerImpl final : public Worker::Service { + public: + WorkerImpl() : acquired_(false) {} + + Status RunTest(ServerContext* ctx, ServerReaderWriter* stream) GRPC_OVERRIDE { + InstanceGuard g(this); + if (!g.Acquired()) { + return Status(RESOURCE_EXHAUSTED); + } + + ClientArgs args; + if (!stream->Read(&args)) { + return Status(INVALID_ARGUMENT); + } + if (!args.has_setup()) { + return Status(INVALID_ARGUMENT); + } + auto client = CreateClient(args.setup()); + if (!client) { + return Status(INVALID_ARGUMENT); + } + + return Status::OK; + } + + Status RunServer(ServerContext* ctx, ServerReaderWriter* stream) GRPC_OVERRIDE { + InstanceGuard g(this); + if (!g.Acquired()) { + return Status(RESOURCE_EXHAUSTED); + } + + ServerArgs args; + if (!stream->Read(&args)) { + return Status(INVALID_ARGUMENT); + } + if (!args.has_config()) { + return Status(INVALID_ARGUMENT); + } + auto server = CreateServer(args.config()); + if (!server) { + return Status(INVALID_ARGUMENT); + } + + return Status::OK; + } + + private: + class InstanceGuard { + public: + InstanceGuard(WorkerImpl* impl) : impl_(impl), acquired_(impl->TryAcquireInstance()) {} + ~InstanceGuard() { if (acquired_) { impl_->ReleaseInstance(); } } + + bool Acquired() const { return acquired_; } + + private: + WorkerImpl* const impl_; + const bool acquired_; + }; + + bool TryAcquireInstance() { + std::lock_guard g(mu_); + if (acquired_) return false; + acquired_ = true; + return true; + } + + void ReleaseInstance() { + std::lock_guard g(mu_); + GPR_ASSERT(acquired_); + acquired_ = false; + } + + std::mutex mu_; + bool acquired_; +}; + +static void RunServer() { + char* server_address = NULL; + gpr_join_host_port(&server_address, "::", FLAGS_driver_port); + + WorkerImpl service; + + ServerBuilder builder; + builder.AddPort(server_address); + builder.RegisterService(&service); + + gpr_free(server_address); + + auto server = builder.BuildAndStart(); + + while (!got_sigint) { + std::this_thread::sleep_for(std::chrono::seconds(5)); + } +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char **argv) { + signal(SIGINT, sigint_handler); + + grpc_init(); + ParseCommandLineFlags(&argc, &argv, true); + + grpc::testing::RunServer(); + + grpc_shutdown(); + return 0; +} From 6af9ed0bf78a1fe6cbfe5e91d44d34da5b152f1b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Mar 2015 22:42:10 -0800 Subject: [PATCH 10/27] Rework QPS client/server Now setup as a driver and N anonymous workers that may become clients or servers. Will convert async soon. --- test/cpp/qps/client.cc | 272 +++++++++++---------------- test/cpp/qps/client.h | 2 + test/cpp/qps/driver.cc | 218 ++++++++++----------- test/cpp/qps/driver.h | 4 + test/cpp/qps/histogram.h | 63 +++++++ test/cpp/qps/qps_driver.cc | 18 +- test/cpp/qps/qpstest.proto | 26 +-- test/cpp/qps/server.cc | 132 +++---------- test/cpp/qps/server.h | 2 + test/cpp/qps/single_run_localhost.sh | 18 +- test/cpp/qps/timer.cc | 6 + test/cpp/qps/timer.h | 2 + test/cpp/qps/worker.cc | 31 ++- 13 files changed, 387 insertions(+), 407 deletions(-) create mode 100644 test/cpp/qps/histogram.h diff --git a/test/cpp/qps/client.cc b/test/cpp/qps/client.cc index 7c9763a332d..827c1ec09b0 100644 --- a/test/cpp/qps/client.cc +++ b/test/cpp/qps/client.cc @@ -53,53 +53,112 @@ #include #include "test/core/util/grpc_profiler.h" #include "test/cpp/util/create_test_channel.h" +#include "test/cpp/qps/client.h" #include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/histogram.h" #include "test/cpp/qps/timer.h" -DEFINE_int32(driver_port, 0, "Client driver port."); - -using grpc::ChannelInterface; -using grpc::CreateTestChannel; -using grpc::ServerBuilder; -using grpc::ServerContext; -using grpc::Status; -using grpc::testing::ClientArgs; -using grpc::testing::ClientConfig; -using grpc::testing::ClientResult; -using grpc::testing::QpsClient; -using grpc::testing::SimpleRequest; -using grpc::testing::SimpleResponse; -using grpc::testing::StatsRequest; -using grpc::testing::TestService; - -// In some distros, gflags is in the namespace google, and in some others, -// in gflags. This hack is enabling us to find both. -namespace google { } -namespace gflags { } -using namespace google; -using namespace gflags; - -static double now() { - gpr_timespec tv = gpr_now(); - return 1e9 * tv.tv_sec + tv.tv_nsec; -} +namespace grpc { +namespace testing { -static bool got_sigint = false; +class SynchronousClient GRPC_FINAL : public Client { + public: + SynchronousClient(const ClientConfig& config) : timer_(new Timer) { + for (int i = 0; i < config.client_channels(); i++) { + channels_.push_back(ClientChannelInfo(config.server_targets(i % config.server_targets_size()), config)); + auto* stub = channels_.back().get_stub(); + for (int j = 0; j < config.outstanding_rpcs_per_channel(); j++) { + threads_.emplace_back(new Thread(stub, config)); + } + } + } -static void sigint_handler(int x) { got_sigint = 1; } + ClientStats Mark() { + Histogram latencies; + std::vector to_merge(threads_.size()); + for (size_t i = 0; i < threads_.size(); i++) { + threads_[i]->BeginSwap(&to_merge[i]); + } + std::unique_ptr timer(new Timer); + timer_.swap(timer); + for (size_t i = 0; i < threads_.size(); i++) { + threads_[i]->EndSwap(); + latencies.Merge(&to_merge[i]); + } + + auto timer_result = timer->Mark(); + + ClientStats stats; + auto* l = stats.mutable_latencies(); + l->set_l_50(latencies.Percentile(50)); + l->set_l_90(latencies.Percentile(90)); + l->set_l_99(latencies.Percentile(99)); + l->set_l_999(latencies.Percentile(99.9)); + stats.set_num_rpcs(latencies.Count()); + stats.set_time_elapsed(timer_result.wall); + stats.set_time_system(timer_result.system); + stats.set_time_user(timer_result.user); + return stats; + } -ClientResult RunTest(const ClientArgs& args) { - const auto& config = args.config(); + private: + class Thread { + public: + Thread(TestService::Stub* stub, const ClientConfig& config) : stub_(stub), config_(config), done_(false), new_(nullptr), impl_([this]() { + SimpleRequest request; + SimpleResponse response; + request.set_response_type( + grpc::testing::PayloadType::COMPRESSABLE); + request.set_response_size(config_.payload_size()); + for (;;) { + { + std::lock_guard g(mu_); + if (done_) return; + if (new_) { + new_->Swap(&histogram_); + new_ = nullptr; + cv_.notify_one(); + } + } + double start = Timer::Now(); + grpc::ClientContext context; + grpc::Status s = + stub_->UnaryCall(&context, request, &response); + histogram_.Add((Timer::Now() - start) * 1e9); + } + }) {} + + ~Thread() { + { + std::lock_guard g(mu_); + done_ = true; + } + impl_.join(); + } + + void BeginSwap(Histogram* n) { + std::lock_guard g(mu_); + new_ = n; + } + + void EndSwap() { + std::unique_lock g(mu_); + cv_.wait(g, [this]() { return new_ == nullptr; }); + } - gpr_log(GPR_INFO, - "QPS test with parameters\n" - "enable_ssl = %d\n" - "client_channels = %d\n" - "client_threads = %d\n" - "num_rpcs = %d\n" - "payload_size = %d\n", - config.enable_ssl(), config.client_channels(), config.client_threads(), config.num_rpcs(), - config.payload_size()); + private: + Thread(const Thread&); + Thread& operator=(const Thread&); + + TestService::Stub* stub_; + ClientConfig config_; + std::mutex mu_; + std::condition_variable cv_; + bool done_; + Histogram *new_; + Histogram histogram_; + std::thread impl_; + }; class ClientChannelInfo { public: @@ -113,133 +172,14 @@ ClientResult RunTest(const ClientArgs& args) { std::shared_ptr channel_; std::unique_ptr stub_; }; - - std::vector channels; - for (int i = 0; i < config.client_channels(); i++) { - channels.push_back(ClientChannelInfo(args.server_targets(i % args.server_targets_size()), config)); - } - - std::vector threads; // Will add threads when ready to execute - std::vector< ::gpr_histogram *> thread_stats(config.client_threads()); - - grpc::ClientContext context_stats_begin; - - grpc_profiler_start("qps_client.prof"); - - Timer timer; - - for (int i = 0; i < config.client_threads(); i++) { - gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); - GPR_ASSERT(hist != NULL); - thread_stats[i] = hist; - - threads.push_back( - std::thread([hist, config, &channels](int channel_num) { - SimpleRequest request; - SimpleResponse response; - request.set_response_type( - grpc::testing::PayloadType::COMPRESSABLE); - request.set_response_size(config.payload_size()); - - for (int j = 0; j < config.num_rpcs(); j++) { - TestService::Stub *stub = - channels[channel_num].get_stub(); - double start = now(); - grpc::ClientContext context; - grpc::Status s = - stub->UnaryCall(&context, request, &response); - gpr_histogram_add(hist, now() - start); - - GPR_ASSERT((s.code() == grpc::StatusCode::OK) && - (response.payload().type() == - grpc::testing::PayloadType::COMPRESSABLE) && - (response.payload().body().length() == - static_cast(config.payload_size()))); - - // Now do runtime round-robin assignment of the next - // channel number - channel_num += config.client_threads(); - channel_num %= config.client_channels(); - } - }, - i % config.client_channels())); - } - - for (auto &t : threads) { - t.join(); - } - - auto timer_result = timer.Mark(); - - grpc_profiler_stop(); - - gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); - GPR_ASSERT(hist != NULL); - - for (int i = 0; i < config.client_threads(); i++) { - gpr_histogram *h = thread_stats[i]; - gpr_log(GPR_INFO, "latency at thread %d (50/90/95/99/99.9): %f/%f/%f/%f/%f", - i, gpr_histogram_percentile(h, 50), gpr_histogram_percentile(h, 90), - gpr_histogram_percentile(h, 95), gpr_histogram_percentile(h, 99), - gpr_histogram_percentile(h, 99.9)); - gpr_histogram_merge(hist, h); - gpr_histogram_destroy(h); - } - - ClientResult result; - auto* latencies = result.mutable_latencies(); - latencies->set_l_50(gpr_histogram_percentile(hist, 50)); - latencies->set_l_90(gpr_histogram_percentile(hist, 90)); - latencies->set_l_99(gpr_histogram_percentile(hist, 99)); - latencies->set_l_999(gpr_histogram_percentile(hist, 99.9)); - result.set_num_rpcs(config.client_threads() * config.num_rpcs()); - result.set_time_elapsed(timer_result.wall); - result.set_time_system(timer_result.system); - result.set_time_user(timer_result.user); - - gpr_histogram_destroy(hist); - - return result; -} - -class ClientImpl final : public QpsClient::Service { - public: - Status RunTest(ServerContext* ctx, const ClientArgs* args, ClientResult* result) override { - *result = ::RunTest(*args); - return Status::OK; - } - - private: - std::mutex client_mu_; + std::vector channels_; + std::vector> threads_; + std::unique_ptr timer_; }; -static void RunServer() { - char* server_address = NULL; - gpr_join_host_port(&server_address, "::", FLAGS_driver_port); - - ClientImpl service; - - ServerBuilder builder; - builder.AddPort(server_address); - builder.RegisterService(&service); - - gpr_free(server_address); - - auto server = builder.BuildAndStart(); - - while (!got_sigint) { - std::this_thread::sleep_for(std::chrono::seconds(5)); - } +std::unique_ptr CreateSynchronousClient(const ClientConfig& config) { + return std::unique_ptr(new SynchronousClient(config)); } -int main(int argc, char **argv) { - signal(SIGINT, sigint_handler); - - grpc_init(); - ParseCommandLineFlags(&argc, &argv, true); - - RunServer(); - - grpc_shutdown(); - return 0; -} +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index ab34970ebd3..97701d3d18f 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -42,6 +42,8 @@ namespace testing { class Client { public: virtual ~Client() {} + + virtual ClientStats Mark() = 0; }; std::unique_ptr CreateSynchronousClient(const ClientConfig& args); diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index a54aad5631f..c090d0377ca 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -48,21 +48,9 @@ using std::list; using std::thread; using std::unique_ptr; using std::vector; -using grpc::string; -using grpc::ChannelArguments; -using grpc::ClientContext; -using grpc::ClientReaderWriter; -using grpc::CreateChannelDeprecated; -using grpc::Status; -using grpc::testing::ClientArgs; -using grpc::testing::ClientConfig; -using grpc::testing::ClientResult; -using grpc::testing::Worker; -using grpc::testing::ServerArgs; -using grpc::testing::ServerConfig; -using grpc::testing::ServerStatus; - -#if 0 + +namespace grpc { +namespace testing { static vector get_hosts(const string& name) { char* env = gpr_getenv(name.c_str()); if (!env) return vector(); @@ -70,119 +58,139 @@ static vector get_hosts(const string& name) { vector out; char* p = env; for (;;) { - char* comma = strchr(p, ','); - if (comma) { - out.emplace_back(p, comma); - p = comma + 1; - } else { - out.emplace_back(p); - gpr_free(env); - return out; - } + char* comma = strchr(p, ','); + if (comma) { + out.emplace_back(p, comma); + p = comma + 1; + } else { + out.emplace_back(p); + gpr_free(env); + return out; + } } } -void RunScenario(const ClientConfig& client_config, size_t num_clients, +void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, const ServerConfig& server_config, size_t num_servers) { // ClientContext allocator (all are destroyed at scope exit) list contexts; auto alloc_context = [&contexts]() { - contexts.emplace_back(); - return &contexts.back(); + contexts.emplace_back(); + return &contexts.back(); }; // Get client, server lists auto workers = get_hosts("QPS_WORKERS"); + ClientConfig client_config = initial_client_config; - GPR_ASSERT(clients.size() >= num_clients); - GPR_ASSERT(servers.size() >= num_servers); + // TODO(ctiller): support running multiple configurations, and binpack client/server pairs + // to available workers + GPR_ASSERT(workers.size() >= num_clients + num_servers); // Trim to just what we need - clients.resize(num_clients); - servers.resize(num_servers); + workers.resize(num_clients + num_servers); // Start servers - vector> server_stubs; - vector>> server_streams; - vector server_targets; - for (const auto& target : servers) { - server_stubs.push_back(QpsServer::NewStub(CreateChannelDeprecated(target, ChannelArguments()))); - auto* stub = server_stubs.back().get(); - ServerArgs args; - *args.mutable_config() = server_config; - server_streams.push_back(stub->RunServer(alloc_context())); - auto* stream = server_streams.back().get(); - if (!stream->Write(args)) { - gpr_log(GPR_ERROR, "Failed starting server"); - return; - } - ServerStatus init_status; - if (!stream->Read(&init_status)) { - gpr_log(GPR_ERROR, "Failed starting server"); - return; - } - char* host; - char* driver_port; - char* cli_target; - gpr_split_host_port(target.c_str(), &host, &driver_port); - gpr_join_host_port(&cli_target, host, init_status.port()); - server_targets.push_back(cli_target); - gpr_free(host); - gpr_free(driver_port); - gpr_free(cli_target); + struct ServerData { + unique_ptr stub; + unique_ptr> stream; + }; + vector servers; + for (size_t i = 0; i < num_servers; i++) { + ServerData sd; + sd.stub = std::move(Worker::NewStub(CreateChannelDeprecated(workers[i], ChannelArguments()))); + ServerArgs args; + *args.mutable_setup() = server_config; + sd.stream = std::move(sd.stub->RunServer(alloc_context())); + GPR_ASSERT(sd.stream->Write(args)); + ServerStatus init_status; + GPR_ASSERT(sd.stream->Read(&init_status)); + char* host; + char* driver_port; + char* cli_target; + gpr_split_host_port(workers[i].c_str(), &host, &driver_port); + gpr_join_host_port(&cli_target, host, init_status.port()); + client_config.add_server_targets(cli_target); + gpr_free(host); + gpr_free(driver_port); + gpr_free(cli_target); + + servers.push_back(std::move(sd)); } // Start clients - class Client { - public: - Client(ClientContext* ctx, const string& target, const ClientArgs& args) - : thread_([ctx, target, args, this]() { - auto stub = QpsClient::NewStub(CreateChannelDeprecated(target, ChannelArguments())); - status_ = stub->RunTest(ctx, args, &result_); - }) {} - - ~Client() { join(); } - - void join() { if (!joined_) { thread_.join(); joined_ = true; } } - - const Status& status() const { return status_; } - const ClientResult& result() const { return result_; } - - private: - bool joined_ = false; - Status status_; - ClientResult result_; - thread thread_; + struct ClientData { + unique_ptr stub; + unique_ptr> stream; }; - list running_clients; - size_t svr_idx = 0; - for (const auto& target : clients) { - ClientArgs args; - *args.mutable_config() = client_config; - for (size_t i = 0; i < num_servers; i++) { - args.add_server_targets(server_targets[svr_idx]); - svr_idx = (svr_idx + 1) % num_servers; - } - - running_clients.emplace_back(alloc_context(), target, args); + vector clients; + for (size_t i = 0; i < num_clients; i++) { + ClientData cd; + cd.stub = std::move(Worker::NewStub(CreateChannelDeprecated(workers[i + num_servers], ChannelArguments()))); + ClientArgs args; + *args.mutable_setup() = client_config; + cd.stream = std::move(cd.stub->RunTest(alloc_context())); + GPR_ASSERT(cd.stream->Write(args)); + ClientStatus init_status; + GPR_ASSERT(cd.stream->Read(&init_status)); + + clients.push_back(std::move(cd)); } - // Finish clients - for (auto& client : running_clients) { - client.join(); - if (!client.status().IsOk()) { - gpr_log(GPR_ERROR, "Client failed"); - return; - } + // Let everything warmup + gpr_log(GPR_INFO, "Warming up"); + gpr_timespec start = gpr_now(); + gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(5))); + + // Start a run + gpr_log(GPR_INFO, "Starting"); + ServerArgs server_mark; + server_mark.mutable_mark(); + ClientArgs client_mark; + client_mark.mutable_mark(); + for (auto& server : servers) { + GPR_ASSERT(server.stream->Write(server_mark)); + } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Write(client_mark)); + } + ServerStatus server_status; + ClientStatus client_status; + for (auto& server : servers) { + GPR_ASSERT(server.stream->Read(&server_status)); } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Read(&client_status)); + } + + // Wait some time + gpr_log(GPR_INFO, "Running"); + gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(15))); - // Finish servers - for (auto& stream : server_streams) { - ServerStatus final_status; - ServerStatus dummy; - if (!stream->WritesDone() || !stream->Read(&final_status) || stream->Read(&dummy) || !stream->Finish().IsOk()) { - gpr_log(GPR_ERROR, "Server protocol error"); - } + // Finish a run + gpr_log(GPR_INFO, "Finishing"); + for (auto& server : servers) { + GPR_ASSERT(server.stream->Write(server_mark)); + } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Write(client_mark)); + } + for (auto& server : servers) { + GPR_ASSERT(server.stream->Read(&server_status)); } + for (auto& client : clients) { + GPR_ASSERT(client.stream->Read(&client_status)); + } + + for (auto& client : clients) { + GPR_ASSERT(client.stream->WritesDone()); + GPR_ASSERT(client.stream->Finish().IsOk()); + } + for (auto& server : servers) { + GPR_ASSERT(server.stream->WritesDone()); + GPR_ASSERT(server.stream->Finish().IsOk()); + } +} + +} } -#endif \ No newline at end of file diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h index 8ac9d2f0a3f..5c548bb8481 100644 --- a/test/cpp/qps/driver.h +++ b/test/cpp/qps/driver.h @@ -36,7 +36,11 @@ #include "test/cpp/qps/qpstest.pb.h" +namespace grpc { +namespace testing { void RunScenario(const grpc::testing::ClientConfig& client_config, size_t num_clients, const grpc::testing::ServerConfig& server_config, size_t num_servers); +} +} #endif diff --git a/test/cpp/qps/histogram.h b/test/cpp/qps/histogram.h new file mode 100644 index 00000000000..b8282a48c23 --- /dev/null +++ b/test/cpp/qps/histogram.h @@ -0,0 +1,63 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_HISTOGRAM_H +#define TEST_QPS_HISTOGRAM_H + +#include + +namespace grpc { +namespace testing { + +class Histogram { + public: + Histogram() : impl_(gpr_histogram_create(0.01, 60e9)) {} + ~Histogram() { gpr_histogram_destroy(impl_); } + + void Merge(Histogram* h) { gpr_histogram_merge(impl_, h->impl_); } + void Add(double value) { gpr_histogram_add(impl_, value); } + double Percentile(double pctile) { return gpr_histogram_percentile(impl_, pctile); } + double Count() { return gpr_histogram_count(impl_); } + void Swap(Histogram* other) { std::swap(impl_, other->impl_); } + + private: + Histogram(const Histogram&); + Histogram& operator=(const Histogram&); + + gpr_histogram* impl_; +}; + +} +} + +#endif /* TEST_QPS_HISTOGRAM_H */ diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc index 88b9d373a11..cbe0b857b04 100644 --- a/test/cpp/qps/qps_driver.cc +++ b/test/cpp/qps/qps_driver.cc @@ -32,6 +32,7 @@ */ #include +#include #include "test/cpp/qps/driver.h" @@ -43,15 +44,18 @@ DEFINE_bool(enable_ssl, false, "Use SSL"); // Server config DEFINE_int32(server_threads, 1, "Number of server threads"); +DEFINE_string(server_type, "SYNCHRONOUS_SERVER", "Server type"); // Client config -DEFINE_int32(client_threads, 1, "Number of client threads"); +DEFINE_int32(outstanding_rpcs_per_channel, 1, "Number of outstanding rpcs per channel"); DEFINE_int32(client_channels, 1, "Number of client channels"); -DEFINE_int32(num_rpcs, 10000, "Number of rpcs per client thread"); DEFINE_int32(payload_size, 1, "Payload size"); +DEFINE_string(client_type, "SYNCHRONOUS_CLIENT", "Client type"); using grpc::testing::ClientConfig; using grpc::testing::ServerConfig; +using grpc::testing::ClientType; +using grpc::testing::ServerType; // In some distros, gflags is in the namespace google, and in some others, // in gflags. This hack is enabling us to find both. @@ -64,14 +68,20 @@ int main(int argc, char **argv) { grpc_init(); ParseCommandLineFlags(&argc, &argv, true); + 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_enable_ssl(FLAGS_enable_ssl); - client_config.set_client_threads(FLAGS_client_threads); + client_config.set_outstanding_rpcs_per_channel(FLAGS_outstanding_rpcs_per_channel); client_config.set_client_channels(FLAGS_client_channels); - client_config.set_num_rpcs(FLAGS_num_rpcs); client_config.set_payload_size(FLAGS_payload_size); ServerConfig server_config; + server_config.set_server_type(server_type); server_config.set_threads(FLAGS_server_threads); server_config.set_enable_ssl(FLAGS_enable_ssl); diff --git a/test/cpp/qps/qpstest.proto b/test/cpp/qps/qpstest.proto index 52d79579446..39d44cd0ed8 100644 --- a/test/cpp/qps/qpstest.proto +++ b/test/cpp/qps/qpstest.proto @@ -89,30 +89,21 @@ message ClientConfig { repeated string server_targets = 1; required ClientType client_type = 2; required bool enable_ssl = 3; - required int32 client_threads = 4; - // We have a configurable number of channels for sending RPCs. - // RPCs are sent round-robin on the available channels by the - // various threads. Interesting cases are 1 global channel or - // 1 per-thread channel, but we can support any number. - // The channels are assigned round-robin on an RPC by RPC basis - // rather than just at initialization time in order to also measure the - // impact of cache thrashing caused by channel changes. This is an issue - // if you are not in one of the above "interesting cases" + required int32 outstanding_rpcs_per_channel = 4; required int32 client_channels = 5; - required int32 num_rpcs = 6; - required int32 payload_size = 7; + required int32 payload_size = 6; } -message ClientStart {} +message Mark {} message ClientArgs { oneof argtype { ClientConfig setup = 1; - ClientStart start = 2; + Mark mark = 2; } } -message ClientResult { +message ClientStats { required Latencies latencies = 1; required int32 num_rpcs = 2; required double time_elapsed = 3; @@ -121,7 +112,7 @@ message ClientResult { } message ClientStatus { - optional ClientResult result = 1; + optional ClientStats stats = 1; } message ServerConfig { @@ -131,7 +122,10 @@ message ServerConfig { } message ServerArgs { - required ServerConfig config = 1; + oneof argtype { + ServerConfig setup = 1; + Mark mark = 2; + } } message ServerStatus { diff --git a/test/cpp/qps/server.cc b/test/cpp/qps/server.cc index 75425c9eb8e..ebe06c1e4a5 100644 --- a/test/cpp/qps/server.cc +++ b/test/cpp/qps/server.cc @@ -48,42 +48,14 @@ #include "src/cpp/server/thread_pool.h" #include "test/core/util/grpc_profiler.h" #include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/server.h" #include "test/cpp/qps/timer.h" #include #include -DEFINE_int32(port, 0, "Server port."); -DEFINE_int32(driver_port, 0, "Server driver port."); - -using grpc::Server; -using grpc::ServerBuilder; -using grpc::ServerContext; -using grpc::ServerReaderWriter; -using grpc::ThreadPool; -using grpc::testing::Payload; -using grpc::testing::PayloadType; -using grpc::testing::ServerStats; -using grpc::testing::SimpleRequest; -using grpc::testing::SimpleResponse; -using grpc::testing::StatsRequest; -using grpc::testing::TestService; -using grpc::testing::QpsServer; -using grpc::testing::ServerArgs; -using grpc::testing::ServerStats; -using grpc::testing::ServerStatus; -using grpc::Status; - -// In some distros, gflags is in the namespace google, and in some others, -// in gflags. This hack is enabling us to find both. -namespace google { } -namespace gflags { } -using namespace google; -using namespace gflags; - -static bool got_sigint = false; - -static void sigint_handler(int x) { got_sigint = 1; } +namespace grpc { +namespace testing { static bool SetPayload(PayloadType type, int size, Payload* payload) { PayloadType response_type = type; @@ -97,8 +69,6 @@ static bool SetPayload(PayloadType type, int size, Payload* payload) { return true; } -namespace { - class TestServiceImpl GRPC_FINAL : public TestService::Service { public: Status UnaryCall(ServerContext* context, const SimpleRequest* request, @@ -113,88 +83,46 @@ class TestServiceImpl GRPC_FINAL : public TestService::Service { } }; -} // namespace - -class ServerImpl : public QpsServer::Service { +class SynchronousServer GRPC_FINAL : public grpc::testing::Server { public: - Status RunServer(ServerContext* ctx, ServerReaderWriter* stream) { - ServerArgs args; - if (!stream->Read(&args)) return Status::OK; + SynchronousServer(const ServerConfig& config, int port) : thread_pool_(config.threads()), impl_(MakeImpl(port)), timer_(new Timer) {} - std::lock_guard lock(server_mu_); + ServerStats Mark() GRPC_OVERRIDE { + std::unique_ptr timer(new Timer); + timer.swap(timer_); - char* server_address = NULL; - gpr_join_host_port(&server_address, "::", FLAGS_port); + auto timer_result = timer->Mark(); - TestServiceImpl service; + ServerStats stats; + stats.set_time_elapsed(timer_result.wall); + stats.set_time_system(timer_result.system); + stats.set_time_user(timer_result.user); + return stats; + } + private: + std::unique_ptr MakeImpl(int port) { ServerBuilder builder; - builder.AddPort(server_address); - builder.RegisterService(&service); - - std::unique_ptr pool(new ThreadPool(args.config().threads())); - builder.SetThreadPool(pool.get()); - - auto server = builder.BuildAndStart(); - gpr_log(GPR_INFO, "Server listening on %s\n", server_address); + char* server_address = NULL; + gpr_join_host_port(&server_address, "::", port); + builder.AddPort(server_address); gpr_free(server_address); - ServerStatus status; - status.set_port(FLAGS_port); - if (!stream->Write(status)) return Status(grpc::UNKNOWN); - - grpc_profiler_start("qps_server.prof"); - Timer timer; - - if (stream->Read(&args)) { - gpr_log(GPR_ERROR, "Got a server request, but not expecting one"); - return Status(grpc::UNKNOWN); - } - - auto timer_result = timer.Mark(); - grpc_profiler_stop(); + builder.RegisterService(&service_); - auto* stats = status.mutable_stats(); - stats->set_time_elapsed(timer_result.wall); - stats->set_time_system(timer_result.system); - stats->set_time_user(timer_result.user); - stream->Write(status); - return Status::OK; + return builder.BuildAndStart(); } - private: - std::mutex server_mu_; + TestServiceImpl service_; + ThreadPool thread_pool_; + std::unique_ptr impl_; + std::unique_ptr timer_; }; -static void RunServer() { - char* server_address = NULL; - gpr_join_host_port(&server_address, "::", FLAGS_driver_port); - - ServerImpl service; - - ServerBuilder builder; - builder.AddPort(server_address); - builder.RegisterService(&service); - - gpr_free(server_address); - - auto server = builder.BuildAndStart(); - - while (!got_sigint) { - sleep(5); - } +std::unique_ptr CreateSynchronousServer(const ServerConfig& config, int port) { + return std::unique_ptr(new SynchronousServer(config, port)); } -int main(int argc, char** argv) { - signal(SIGINT, sigint_handler); - - grpc_init(); - ParseCommandLineFlags(&argc, &argv, true); - - GPR_ASSERT(FLAGS_port != 0); - RunServer(); - - grpc_shutdown(); - return 0; -} +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h index 25c15e4d0cc..35d1aed19f7 100644 --- a/test/cpp/qps/server.h +++ b/test/cpp/qps/server.h @@ -42,6 +42,8 @@ namespace testing { class Server { public: virtual ~Server() {} + + virtual ServerStats Mark() = 0; }; std::unique_ptr CreateSynchronousServer(const ServerConfig& config, int port); diff --git a/test/cpp/qps/single_run_localhost.sh b/test/cpp/qps/single_run_localhost.sh index 310a0824bb3..2f60b4e49de 100755 --- a/test/cpp/qps/single_run_localhost.sh +++ b/test/cpp/qps/single_run_localhost.sh @@ -6,25 +6,23 @@ set -ex cd $(dirname $0)/../../.. -killall qps_server qps_client || true +killall qps_worker || true config=opt NUMCPUS=`python2.7 -c 'import multiprocessing; print multiprocessing.cpu_count()'` -make CONFIG=$config qps_client qps_server qps_driver -j$NUMCPUS +make CONFIG=$config qps_worker qps_driver -j$NUMCPUS -bins/$config/qps_server -driver_port 10000 -port 10002 & -SERVER_PID=$! -bins/$config/qps_client -driver_port 10001 & -CLIENT_PID=$! +bins/$config/qps_worker -driver_port 10000 -server_port 10001 & +PID1=$! +bins/$config/qps_worker -driver_port 10010 -server_port 10011 & +PID2=$! -export QPS_SERVERS=localhost:10000 -export QPS_CLIENTS=localhost:10001 +export QPS_WORKERS="localhost:10000,localhost:10010" bins/$config/qps_driver $* -kill -2 $CLIENT_PID -kill -2 $SERVER_PID +kill -2 $PID1 $PID2 wait diff --git a/test/cpp/qps/timer.cc b/test/cpp/qps/timer.cc index 5a5be97071b..3c1342041cf 100644 --- a/test/cpp/qps/timer.cc +++ b/test/cpp/qps/timer.cc @@ -35,9 +35,15 @@ #include #include +#include Timer::Timer() : start_(Sample()) {} +double Timer::Now() { + auto ts = gpr_now(); + return ts.tv_sec + 1e-9 * ts.tv_nsec; +} + static double time_double(struct timeval* tv) { return tv->tv_sec + 1e-6 * tv->tv_usec; } diff --git a/test/cpp/qps/timer.h b/test/cpp/qps/timer.h index 8a229cbd305..1c9a006b937 100644 --- a/test/cpp/qps/timer.h +++ b/test/cpp/qps/timer.h @@ -46,6 +46,8 @@ class Timer { Result Mark(); + static double Now(); + private: static Result Sample(); diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc index 749420bd694..741dfc000d3 100644 --- a/test/cpp/qps/worker.cc +++ b/test/cpp/qps/worker.cc @@ -78,7 +78,7 @@ namespace testing { std::unique_ptr CreateClient(const ClientConfig& config) { switch (config.client_type()) { case ClientType::SYNCHRONOUS_CLIENT: return CreateSynchronousClient(config); - case ClientType::ASYNC_CLIENT: return CreateAsyncClient(config); + case ClientType::ASYNC_CLIENT: abort(); //return CreateAsyncClient(config); } abort(); } @@ -86,7 +86,7 @@ std::unique_ptr CreateClient(const ClientConfig& config) { std::unique_ptr CreateServer(const ServerConfig& config) { switch (config.server_type()) { case ServerType::SYNCHRONOUS_SERVER: return CreateSynchronousServer(config, FLAGS_server_port); - case ServerType::ASYNC_SERVER: return CreateAsyncServer(config, FLAGS_server_port); + case ServerType::ASYNC_SERVER: abort(); //return CreateAsyncServer(config, FLAGS_server_port); } abort(); } @@ -112,6 +112,17 @@ class WorkerImpl final : public Worker::Service { if (!client) { return Status(INVALID_ARGUMENT); } + ClientStatus status; + if (!stream->Write(status)) { + return Status(UNKNOWN); + } + while (stream->Read(&args)) { + if (!args.has_mark()) { + return Status(INVALID_ARGUMENT); + } + *status.mutable_stats() = client->Mark(); + stream->Write(status); + } return Status::OK; } @@ -126,13 +137,25 @@ class WorkerImpl final : public Worker::Service { if (!stream->Read(&args)) { return Status(INVALID_ARGUMENT); } - if (!args.has_config()) { + if (!args.has_setup()) { return Status(INVALID_ARGUMENT); } - auto server = CreateServer(args.config()); + auto server = CreateServer(args.setup()); if (!server) { return Status(INVALID_ARGUMENT); } + ServerStatus status; + status.set_port(FLAGS_server_port); + if (!stream->Write(status)) { + return Status(UNKNOWN); + } + while (stream->Read(&args)) { + if (!args.has_mark()) { + return Status(INVALID_ARGUMENT); + } + *status.mutable_stats() = server->Mark(); + stream->Write(status); + } return Status::OK; } From 10923c2fb5b1d70d13b158712da17cbefbdcd835 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 Mar 2015 14:24:49 -0800 Subject: [PATCH 11/27] Formatting --- test/cpp/qps/client.cc | 61 +++++++++--------- test/cpp/qps/driver.cc | 10 +-- test/cpp/qps/driver.h | 6 +- test/cpp/qps/histogram.h | 7 ++- test/cpp/qps/qps_driver.cc | 14 +++-- test/cpp/qps/server.cc | 8 ++- test/cpp/qps/server.h | 3 +- test/cpp/qps/timer.h | 8 +-- test/cpp/qps/worker.cc | 123 ++++++++++++++++++++----------------- 9 files changed, 135 insertions(+), 105 deletions(-) diff --git a/test/cpp/qps/client.cc b/test/cpp/qps/client.cc index 827c1ec09b0..951670c6127 100644 --- a/test/cpp/qps/client.cc +++ b/test/cpp/qps/client.cc @@ -65,7 +65,8 @@ class SynchronousClient GRPC_FINAL : public Client { public: SynchronousClient(const ClientConfig& config) : timer_(new Timer) { for (int i = 0; i < config.client_channels(); i++) { - channels_.push_back(ClientChannelInfo(config.server_targets(i % config.server_targets_size()), config)); + channels_.push_back(ClientChannelInfo( + config.server_targets(i % config.server_targets_size()), config)); auto* stub = channels_.back().get_stub(); for (int j = 0; j < config.outstanding_rpcs_per_channel(); j++) { threads_.emplace_back(new Thread(stub, config)); @@ -104,29 +105,32 @@ class SynchronousClient GRPC_FINAL : public Client { private: class Thread { public: - Thread(TestService::Stub* stub, const ClientConfig& config) : stub_(stub), config_(config), done_(false), new_(nullptr), impl_([this]() { - SimpleRequest request; - SimpleResponse response; - request.set_response_type( - grpc::testing::PayloadType::COMPRESSABLE); - request.set_response_size(config_.payload_size()); - for (;;) { - { - std::lock_guard g(mu_); - if (done_) return; - if (new_) { - new_->Swap(&histogram_); - new_ = nullptr; - cv_.notify_one(); - } - } - double start = Timer::Now(); - grpc::ClientContext context; - grpc::Status s = - stub_->UnaryCall(&context, request, &response); - histogram_.Add((Timer::Now() - start) * 1e9); - } - }) {} + Thread(TestService::Stub* stub, const ClientConfig& config) + : stub_(stub), + config_(config), + done_(false), + new_(nullptr), + impl_([this]() { + SimpleRequest request; + SimpleResponse response; + request.set_response_type(grpc::testing::PayloadType::COMPRESSABLE); + request.set_response_size(config_.payload_size()); + for (;;) { + { + std::lock_guard g(mu_); + if (done_) return; + if (new_) { + new_->Swap(&histogram_); + new_ = nullptr; + cv_.notify_one(); + } + } + double start = Timer::Now(); + grpc::ClientContext context; + grpc::Status s = stub_->UnaryCall(&context, request, &response); + histogram_.Add((Timer::Now() - start) * 1e9); + } + }) {} ~Thread() { { @@ -155,18 +159,19 @@ class SynchronousClient GRPC_FINAL : public Client { std::mutex mu_; std::condition_variable cv_; bool done_; - Histogram *new_; + Histogram* new_; Histogram histogram_; std::thread impl_; }; class ClientChannelInfo { public: - explicit ClientChannelInfo(const grpc::string& target, const ClientConfig& config) + explicit ClientChannelInfo(const grpc::string& target, + const ClientConfig& config) : channel_(CreateTestChannel(target, config.enable_ssl())), stub_(TestService::NewStub(channel_)) {} - ChannelInterface *get_channel() { return channel_.get(); } - TestService::Stub *get_stub() { return stub_.get(); } + ChannelInterface* get_channel() { return channel_.get(); } + TestService::Stub* get_stub() { return stub_.get(); } private: std::shared_ptr channel_; diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index c090d0377ca..0b200400cb3 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -83,7 +83,8 @@ void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, auto workers = get_hosts("QPS_WORKERS"); ClientConfig client_config = initial_client_config; - // TODO(ctiller): support running multiple configurations, and binpack client/server pairs + // TODO(ctiller): support running multiple configurations, and binpack + // client/server pairs // to available workers GPR_ASSERT(workers.size() >= num_clients + num_servers); @@ -98,7 +99,8 @@ void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, vector servers; for (size_t i = 0; i < num_servers; i++) { ServerData sd; - sd.stub = std::move(Worker::NewStub(CreateChannelDeprecated(workers[i], ChannelArguments()))); + sd.stub = std::move(Worker::NewStub( + CreateChannelDeprecated(workers[i], ChannelArguments()))); ServerArgs args; *args.mutable_setup() = server_config; sd.stream = std::move(sd.stub->RunServer(alloc_context())); @@ -126,7 +128,8 @@ void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, vector clients; for (size_t i = 0; i < num_clients; i++) { ClientData cd; - cd.stub = std::move(Worker::NewStub(CreateChannelDeprecated(workers[i + num_servers], ChannelArguments()))); + cd.stub = std::move(Worker::NewStub( + CreateChannelDeprecated(workers[i + num_servers], ChannelArguments()))); ClientArgs args; *args.mutable_setup() = client_config; cd.stream = std::move(cd.stub->RunTest(alloc_context())); @@ -191,6 +194,5 @@ void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, GPR_ASSERT(server.stream->Finish().IsOk()); } } - } } diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h index 5c548bb8481..f11030a63ea 100644 --- a/test/cpp/qps/driver.h +++ b/test/cpp/qps/driver.h @@ -38,8 +38,10 @@ namespace grpc { namespace testing { -void RunScenario(const grpc::testing::ClientConfig& client_config, size_t num_clients, - const grpc::testing::ServerConfig& server_config, size_t num_servers); +void RunScenario(const grpc::testing::ClientConfig& client_config, + size_t num_clients, + const grpc::testing::ServerConfig& server_config, + size_t num_servers); } } diff --git a/test/cpp/qps/histogram.h b/test/cpp/qps/histogram.h index b8282a48c23..e6605790082 100644 --- a/test/cpp/qps/histogram.h +++ b/test/cpp/qps/histogram.h @@ -46,7 +46,9 @@ class Histogram { void Merge(Histogram* h) { gpr_histogram_merge(impl_, h->impl_); } void Add(double value) { gpr_histogram_add(impl_, value); } - double Percentile(double pctile) { return gpr_histogram_percentile(impl_, pctile); } + double Percentile(double pctile) { + return gpr_histogram_percentile(impl_, pctile); + } double Count() { return gpr_histogram_count(impl_); } void Swap(Histogram* other) { std::swap(impl_, other->impl_); } @@ -56,8 +58,7 @@ class Histogram { gpr_histogram* impl_; }; - } } -#endif /* TEST_QPS_HISTOGRAM_H */ +#endif /* TEST_QPS_HISTOGRAM_H */ diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc index cbe0b857b04..d54a6c84aac 100644 --- a/test/cpp/qps/qps_driver.cc +++ b/test/cpp/qps/qps_driver.cc @@ -47,7 +47,8 @@ DEFINE_int32(server_threads, 1, "Number of server threads"); DEFINE_string(server_type, "SYNCHRONOUS_SERVER", "Server type"); // Client config -DEFINE_int32(outstanding_rpcs_per_channel, 1, "Number of outstanding rpcs per channel"); +DEFINE_int32(outstanding_rpcs_per_channel, 1, + "Number of outstanding rpcs per channel"); DEFINE_int32(client_channels, 1, "Number of client channels"); DEFINE_int32(payload_size, 1, "Payload size"); DEFINE_string(client_type, "SYNCHRONOUS_CLIENT", "Client type"); @@ -59,8 +60,8 @@ using grpc::testing::ServerType; // In some distros, gflags is in the namespace google, and in some others, // in gflags. This hack is enabling us to find both. -namespace google { } -namespace gflags { } +namespace google {} +namespace gflags {} using namespace google; using namespace gflags; @@ -76,7 +77,8 @@ int main(int argc, char **argv) { ClientConfig client_config; client_config.set_client_type(client_type); client_config.set_enable_ssl(FLAGS_enable_ssl); - client_config.set_outstanding_rpcs_per_channel(FLAGS_outstanding_rpcs_per_channel); + client_config.set_outstanding_rpcs_per_channel( + FLAGS_outstanding_rpcs_per_channel); client_config.set_client_channels(FLAGS_client_channels); client_config.set_payload_size(FLAGS_payload_size); @@ -85,9 +87,9 @@ int main(int argc, char **argv) { server_config.set_threads(FLAGS_server_threads); server_config.set_enable_ssl(FLAGS_enable_ssl); - RunScenario(client_config, FLAGS_num_clients, server_config, FLAGS_num_servers); + RunScenario(client_config, FLAGS_num_clients, server_config, + FLAGS_num_servers); grpc_shutdown(); return 0; } - diff --git a/test/cpp/qps/server.cc b/test/cpp/qps/server.cc index ebe06c1e4a5..8424dbafe97 100644 --- a/test/cpp/qps/server.cc +++ b/test/cpp/qps/server.cc @@ -85,7 +85,10 @@ class TestServiceImpl GRPC_FINAL : public TestService::Service { class SynchronousServer GRPC_FINAL : public grpc::testing::Server { public: - SynchronousServer(const ServerConfig& config, int port) : thread_pool_(config.threads()), impl_(MakeImpl(port)), timer_(new Timer) {} + SynchronousServer(const ServerConfig& config, int port) + : thread_pool_(config.threads()), + impl_(MakeImpl(port)), + timer_(new Timer) {} ServerStats Mark() GRPC_OVERRIDE { std::unique_ptr timer(new Timer); @@ -120,7 +123,8 @@ class SynchronousServer GRPC_FINAL : public grpc::testing::Server { std::unique_ptr timer_; }; -std::unique_ptr CreateSynchronousServer(const ServerConfig& config, int port) { +std::unique_ptr CreateSynchronousServer( + const ServerConfig& config, int port) { return std::unique_ptr(new SynchronousServer(config, port)); } diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h index 35d1aed19f7..3542c17a6a2 100644 --- a/test/cpp/qps/server.h +++ b/test/cpp/qps/server.h @@ -46,7 +46,8 @@ class Server { virtual ServerStats Mark() = 0; }; -std::unique_ptr CreateSynchronousServer(const ServerConfig& config, int port); +std::unique_ptr CreateSynchronousServer(const ServerConfig& config, + int port); std::unique_ptr CreateAsyncServer(const ServerConfig& config, int port); } // namespace testing diff --git a/test/cpp/qps/timer.h b/test/cpp/qps/timer.h index 1c9a006b937..30dbd7e7d50 100644 --- a/test/cpp/qps/timer.h +++ b/test/cpp/qps/timer.h @@ -39,9 +39,9 @@ class Timer { Timer(); struct Result { - double wall; - double user; - double system; + double wall; + double user; + double system; }; Result Mark(); @@ -54,4 +54,4 @@ class Timer { const Result start_; }; -#endif // TEST_QPS_TIMER_H +#endif // TEST_QPS_TIMER_H diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc index 741dfc000d3..1279afc18c4 100644 --- a/test/cpp/qps/worker.cc +++ b/test/cpp/qps/worker.cc @@ -63,8 +63,8 @@ DEFINE_int32(server_port, 0, "Spawned server port."); // In some distros, gflags is in the namespace google, and in some others, // in gflags. This hack is enabling us to find both. -namespace google { } -namespace gflags { } +namespace google {} +namespace gflags {} using namespace google; using namespace gflags; @@ -77,16 +77,20 @@ namespace testing { std::unique_ptr CreateClient(const ClientConfig& config) { switch (config.client_type()) { - case ClientType::SYNCHRONOUS_CLIENT: return CreateSynchronousClient(config); - case ClientType::ASYNC_CLIENT: abort(); //return CreateAsyncClient(config); + case ClientType::SYNCHRONOUS_CLIENT: + return CreateSynchronousClient(config); + case ClientType::ASYNC_CLIENT: + abort(); // return CreateAsyncClient(config); } abort(); } std::unique_ptr CreateServer(const ServerConfig& config) { switch (config.server_type()) { - case ServerType::SYNCHRONOUS_SERVER: return CreateSynchronousServer(config, FLAGS_server_port); - case ServerType::ASYNC_SERVER: abort(); //return CreateAsyncServer(config, FLAGS_server_port); + case ServerType::SYNCHRONOUS_SERVER: + return CreateSynchronousServer(config, FLAGS_server_port); + case ServerType::ASYNC_SERVER: + abort(); // return CreateAsyncServer(config, FLAGS_server_port); } abort(); } @@ -95,23 +99,25 @@ class WorkerImpl final : public Worker::Service { public: WorkerImpl() : acquired_(false) {} - Status RunTest(ServerContext* ctx, ServerReaderWriter* stream) GRPC_OVERRIDE { - InstanceGuard g(this); - if (!g.Acquired()) { - return Status(RESOURCE_EXHAUSTED); - } - - ClientArgs args; - if (!stream->Read(&args)) { - return Status(INVALID_ARGUMENT); - } - if (!args.has_setup()) { - return Status(INVALID_ARGUMENT); - } - auto client = CreateClient(args.setup()); - if (!client) { - return Status(INVALID_ARGUMENT); - } + Status RunTest(ServerContext* ctx, + ServerReaderWriter* stream) + GRPC_OVERRIDE { + InstanceGuard g(this); + if (!g.Acquired()) { + return Status(RESOURCE_EXHAUSTED); + } + + ClientArgs args; + if (!stream->Read(&args)) { + return Status(INVALID_ARGUMENT); + } + if (!args.has_setup()) { + return Status(INVALID_ARGUMENT); + } + auto client = CreateClient(args.setup()); + if (!client) { + return Status(INVALID_ARGUMENT); + } ClientStatus status; if (!stream->Write(status)) { return Status(UNKNOWN); @@ -127,23 +133,25 @@ class WorkerImpl final : public Worker::Service { return Status::OK; } - Status RunServer(ServerContext* ctx, ServerReaderWriter* stream) GRPC_OVERRIDE { - InstanceGuard g(this); - if (!g.Acquired()) { - return Status(RESOURCE_EXHAUSTED); - } - - ServerArgs args; - if (!stream->Read(&args)) { - return Status(INVALID_ARGUMENT); - } - if (!args.has_setup()) { - return Status(INVALID_ARGUMENT); - } - auto server = CreateServer(args.setup()); - if (!server) { - return Status(INVALID_ARGUMENT); - } + Status RunServer(ServerContext* ctx, + ServerReaderWriter* stream) + GRPC_OVERRIDE { + InstanceGuard g(this); + if (!g.Acquired()) { + return Status(RESOURCE_EXHAUSTED); + } + + ServerArgs args; + if (!stream->Read(&args)) { + return Status(INVALID_ARGUMENT); + } + if (!args.has_setup()) { + return Status(INVALID_ARGUMENT); + } + auto server = CreateServer(args.setup()); + if (!server) { + return Status(INVALID_ARGUMENT); + } ServerStatus status; status.set_port(FLAGS_server_port); if (!stream->Write(status)) { @@ -163,27 +171,32 @@ class WorkerImpl final : public Worker::Service { private: class InstanceGuard { public: - InstanceGuard(WorkerImpl* impl) : impl_(impl), acquired_(impl->TryAcquireInstance()) {} - ~InstanceGuard() { if (acquired_) { impl_->ReleaseInstance(); } } + InstanceGuard(WorkerImpl* impl) + : impl_(impl), acquired_(impl->TryAcquireInstance()) {} + ~InstanceGuard() { + if (acquired_) { + impl_->ReleaseInstance(); + } + } - bool Acquired() const { return acquired_; } + bool Acquired() const { return acquired_; } private: - WorkerImpl* const impl_; - const bool acquired_; + WorkerImpl* const impl_; + const bool acquired_; }; bool TryAcquireInstance() { - std::lock_guard g(mu_); - if (acquired_) return false; - acquired_ = true; - return true; + std::lock_guard g(mu_); + if (acquired_) return false; + acquired_ = true; + return true; } void ReleaseInstance() { - std::lock_guard g(mu_); - GPR_ASSERT(acquired_); - acquired_ = false; + std::lock_guard g(mu_); + GPR_ASSERT(acquired_); + acquired_ = false; } std::mutex mu_; @@ -209,10 +222,10 @@ static void RunServer() { } } -} // namespace testing -} // namespace grpc +} // namespace testing +} // namespace grpc -int main(int argc, char **argv) { +int main(int argc, char** argv) { signal(SIGINT, sigint_handler); grpc_init(); From a8672573b8c40b36d901a46549f87734ab81815b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 Mar 2015 15:22:00 -0800 Subject: [PATCH 12/27] Re-generate --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index ee900e0442e..76949c7f9dc 100644 --- a/Makefile +++ b/Makefile @@ -7985,16 +7985,16 @@ $(BINDIR)/$(CONFIG)/pubsub_client: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/pubsub_client: $(PROTOBUF_DEP) $(PUBSUB_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(BINDIR)/$(CONFIG)/pubsub_client: $(PROTOBUF_DEP) $(PUBSUB_CLIENT_OBJS) $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(PUBSUB_CLIENT_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/pubsub_client + $(Q) $(LDXX) $(LDFLAGS) $(PUBSUB_CLIENT_OBJS) $(GTEST_LIB) $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/pubsub_client endif endif -$(OBJDIR)/$(CONFIG)/examples/pubsub/main.o: $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/examples/pubsub/main.o: $(LIBDIR)/$(CONFIG)/libpubsub_client_lib.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_pubsub_client: $(PUBSUB_CLIENT_OBJS:.o=.dep) From 76877c3f6612f9c19103ce0d3273952d7f1f0350 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 Mar 2015 16:04:23 -0800 Subject: [PATCH 13/27] Generate latencies in driver --- include/grpc/support/histogram.h | 10 +++++++++ src/core/support/histogram.c | 35 +++++++++++++++++++++++--------- test/cpp/qps/client.cc | 7 +------ test/cpp/qps/driver.cc | 6 ++++++ test/cpp/qps/histogram.h | 16 +++++++++++++++ test/cpp/qps/qpstest.proto | 15 +++++++------- test/cpp/qps/worker.cc | 1 + 7 files changed, 67 insertions(+), 23 deletions(-) diff --git a/include/grpc/support/histogram.h b/include/grpc/support/histogram.h index 31f7fedfd5d..64d08f0bf1f 100644 --- a/include/grpc/support/histogram.h +++ b/include/grpc/support/histogram.h @@ -34,6 +34,9 @@ #ifndef GRPC_SUPPORT_HISTOGRAM_H #define GRPC_SUPPORT_HISTOGRAM_H +#include +#include + #ifdef __cplusplus extern "C" { #endif @@ -59,6 +62,13 @@ double gpr_histogram_count(gpr_histogram *histogram); double gpr_histogram_sum(gpr_histogram *histogram); double gpr_histogram_sum_of_squares(gpr_histogram *histogram); +const gpr_uint32 *gpr_histogram_get_contents(gpr_histogram *histogram, + size_t *count); +void gpr_histogram_merge_contents(gpr_histogram *histogram, + const gpr_uint32 *data, size_t data_count, + double min_seen, double max_seen, double sum, + double sum_of_squares, double count); + #ifdef __cplusplus } #endif diff --git a/src/core/support/histogram.c b/src/core/support/histogram.c index eacb77082f9..2d52786ce52 100644 --- a/src/core/support/histogram.c +++ b/src/core/support/histogram.c @@ -126,25 +126,35 @@ void gpr_histogram_add(gpr_histogram *h, double x) { } int gpr_histogram_merge(gpr_histogram *dst, gpr_histogram *src) { - size_t i; if ((dst->num_buckets != src->num_buckets) || (dst->multiplier != src->multiplier)) { /* Fail because these histograms don't match */ return 0; } - dst->sum += src->sum; - dst->sum_of_squares += src->sum_of_squares; - dst->count += src->count; - if (src->min_seen < dst->min_seen) { - dst->min_seen = src->min_seen; + gpr_histogram_merge_contents(dst, src->buckets, src->num_buckets, + src->min_seen, src->max_seen, src->sum, + src->sum_of_squares, src->count); + return 1; +} + +void gpr_histogram_merge_contents(gpr_histogram *dst, const gpr_uint32 *data, + size_t data_count, double min_seen, + double max_seen, double sum, + double sum_of_squares, double count) { + size_t i; + GPR_ASSERT(dst->num_buckets == data_count); + dst->sum += sum; + dst->sum_of_squares += sum_of_squares; + dst->count += count; + if (min_seen < dst->min_seen) { + dst->min_seen = min_seen; } - if (src->max_seen > dst->max_seen) { - dst->max_seen = src->max_seen; + if (max_seen > dst->max_seen) { + dst->max_seen = max_seen; } for (i = 0; i < dst->num_buckets; i++) { - dst->buckets[i] += src->buckets[i]; + dst->buckets[i] += data[i]; } - return 1; } static double threshold_for_count_below(gpr_histogram *h, double count_below) { @@ -222,3 +232,8 @@ double gpr_histogram_sum(gpr_histogram *h) { return h->sum; } double gpr_histogram_sum_of_squares(gpr_histogram *h) { return h->sum_of_squares; } + +const gpr_uint32 *gpr_histogram_get_contents(gpr_histogram *h, size_t *size) { + *size = h->num_buckets; + return h->buckets; +} \ No newline at end of file diff --git a/test/cpp/qps/client.cc b/test/cpp/qps/client.cc index 951670c6127..877007038ef 100644 --- a/test/cpp/qps/client.cc +++ b/test/cpp/qps/client.cc @@ -90,12 +90,7 @@ class SynchronousClient GRPC_FINAL : public Client { auto timer_result = timer->Mark(); ClientStats stats; - auto* l = stats.mutable_latencies(); - l->set_l_50(latencies.Percentile(50)); - l->set_l_90(latencies.Percentile(90)); - l->set_l_99(latencies.Percentile(99)); - l->set_l_999(latencies.Percentile(99.9)); - stats.set_num_rpcs(latencies.Count()); + latencies.FillProto(stats.mutable_latencies()); stats.set_time_elapsed(timer_result.wall); stats.set_time_system(timer_result.system); stats.set_time_user(timer_result.user); diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index 0b200400cb3..a9bd4b9dbd0 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -43,6 +43,7 @@ #include #include #include +#include "test/cpp/qps/histogram.h" using std::list; using std::thread; @@ -171,6 +172,7 @@ void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(15))); // Finish a run + Histogram latencies; gpr_log(GPR_INFO, "Finishing"); for (auto& server : servers) { GPR_ASSERT(server.stream->Write(server_mark)); @@ -183,6 +185,7 @@ void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, } for (auto& client : clients) { GPR_ASSERT(client.stream->Read(&client_status)); + latencies.MergeProto(client_status.stats().latencies()); } for (auto& client : clients) { @@ -193,6 +196,9 @@ void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, GPR_ASSERT(server.stream->WritesDone()); GPR_ASSERT(server.stream->Finish().IsOk()); } + + gpr_log(GPR_INFO, "Latencies (50/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f us", + latencies.Percentile(50) / 1e3, latencies.Percentile(95) / 1e3, latencies.Percentile(99) / 1e3, latencies.Percentile(99.9) / 1e3); } } } diff --git a/test/cpp/qps/histogram.h b/test/cpp/qps/histogram.h index e6605790082..a7ccc09ef9b 100644 --- a/test/cpp/qps/histogram.h +++ b/test/cpp/qps/histogram.h @@ -35,6 +35,7 @@ #define TEST_QPS_HISTOGRAM_H #include +#include "test/cpp/qps/qpstest.pb.h" namespace grpc { namespace testing { @@ -51,6 +52,21 @@ class Histogram { } double Count() { return gpr_histogram_count(impl_); } void Swap(Histogram* other) { std::swap(impl_, other->impl_); } + void FillProto(HistogramData* p) { + size_t n; + const auto* data = gpr_histogram_get_contents(impl_, &n); + for (size_t i = 0; i < n; i++) { + p->add_bucket(data[i]); + } + p->set_min_seen(gpr_histogram_minimum(impl_)); + p->set_max_seen(gpr_histogram_maximum(impl_)); + p->set_sum(gpr_histogram_sum(impl_)); + p->set_sum_of_squares(gpr_histogram_sum_of_squares(impl_)); + p->set_count(gpr_histogram_count(impl_)); + } + void MergeProto(const HistogramData& p) { + gpr_histogram_merge_contents(impl_, &*p.bucket().begin(), p.bucket_size(), p.min_seen(), p.max_seen(), p.sum(), p.sum_of_squares(), p.count()); + } private: Histogram(const Histogram&); diff --git a/test/cpp/qps/qpstest.proto b/test/cpp/qps/qpstest.proto index 39d44cd0ed8..6543e64a014 100644 --- a/test/cpp/qps/qpstest.proto +++ b/test/cpp/qps/qpstest.proto @@ -68,11 +68,13 @@ message Payload { optional bytes body = 2; } -message Latencies { - required double l_50 = 1; - required double l_90 = 2; - required double l_99 = 3; - required double l_999 = 4; +message HistogramData { + repeated uint32 bucket = 1; + required double min_seen = 2; + required double max_seen = 3; + required double sum = 4; + required double sum_of_squares = 5; + required double count = 6; } enum ClientType { @@ -104,8 +106,7 @@ message ClientArgs { } message ClientStats { - required Latencies latencies = 1; - required int32 num_rpcs = 2; + required HistogramData latencies = 1; required double time_elapsed = 3; required double time_user = 4; required double time_system = 5; diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc index 1279afc18c4..b5dbc1570db 100644 --- a/test/cpp/qps/worker.cc +++ b/test/cpp/qps/worker.cc @@ -169,6 +169,7 @@ class WorkerImpl final : public Worker::Service { } private: + // Protect against multiple clients using this worker at once. class InstanceGuard { public: InstanceGuard(WorkerImpl* impl) From d701c5f5c3a46d3e48bc36e230c099ec89e817e8 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 Mar 2015 16:05:04 -0800 Subject: [PATCH 14/27] Formatting --- test/cpp/qps/driver.cc | 3 ++- test/cpp/qps/histogram.h | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index a9bd4b9dbd0..16a82e72cd6 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -198,7 +198,8 @@ void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, } gpr_log(GPR_INFO, "Latencies (50/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f us", - latencies.Percentile(50) / 1e3, latencies.Percentile(95) / 1e3, latencies.Percentile(99) / 1e3, latencies.Percentile(99.9) / 1e3); + latencies.Percentile(50) / 1e3, latencies.Percentile(95) / 1e3, + latencies.Percentile(99) / 1e3, latencies.Percentile(99.9) / 1e3); } } } diff --git a/test/cpp/qps/histogram.h b/test/cpp/qps/histogram.h index a7ccc09ef9b..e7d10e13115 100644 --- a/test/cpp/qps/histogram.h +++ b/test/cpp/qps/histogram.h @@ -65,7 +65,9 @@ class Histogram { p->set_count(gpr_histogram_count(impl_)); } void MergeProto(const HistogramData& p) { - gpr_histogram_merge_contents(impl_, &*p.bucket().begin(), p.bucket_size(), p.min_seen(), p.max_seen(), p.sum(), p.sum_of_squares(), p.count()); + gpr_histogram_merge_contents(impl_, &*p.bucket().begin(), p.bucket_size(), + p.min_seen(), p.max_seen(), p.sum(), + p.sum_of_squares(), p.count()); } private: From f282514389ca66883498c3b8f9d150d54c998689 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 Mar 2015 17:15:36 -0800 Subject: [PATCH 15/27] Print resource utilization --- src/core/support/histogram.c | 2 +- test/cpp/qps/driver.cc | 19 ++++++------ test/cpp/qps/driver.h | 19 ++++++++++-- test/cpp/qps/histogram.h | 5 ++- test/cpp/qps/qps_driver.cc | 14 ++++++++- test/cpp/qps/stats.h | 60 ++++++++++++++++++++++++++++++++++++ 6 files changed, 104 insertions(+), 15 deletions(-) create mode 100644 test/cpp/qps/stats.h diff --git a/src/core/support/histogram.c b/src/core/support/histogram.c index 2d52786ce52..ed344b43e8d 100644 --- a/src/core/support/histogram.c +++ b/src/core/support/histogram.c @@ -236,4 +236,4 @@ double gpr_histogram_sum_of_squares(gpr_histogram *h) { const gpr_uint32 *gpr_histogram_get_contents(gpr_histogram *h, size_t *size) { *size = h->num_buckets; return h->buckets; -} \ No newline at end of file +} diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index 16a82e72cd6..de1ccce3d72 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -71,7 +71,7 @@ static vector get_hosts(const string& name) { } } -void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, +ScenarioResult RunScenario(const ClientConfig& initial_client_config, size_t num_clients, const ServerConfig& server_config, size_t num_servers) { // ClientContext allocator (all are destroyed at scope exit) list contexts; @@ -172,7 +172,7 @@ void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(15))); // Finish a run - Histogram latencies; + ScenarioResult result; gpr_log(GPR_INFO, "Finishing"); for (auto& server : servers) { GPR_ASSERT(server.stream->Write(server_mark)); @@ -182,10 +182,14 @@ void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, } for (auto& server : servers) { GPR_ASSERT(server.stream->Read(&server_status)); + const auto& stats = server_status.stats(); + result.server_resources.push_back(ResourceUsage{stats.time_elapsed(), stats.time_user(), stats.time_system()}); } for (auto& client : clients) { GPR_ASSERT(client.stream->Read(&client_status)); - latencies.MergeProto(client_status.stats().latencies()); + const auto& stats = client_status.stats(); + result.latencies.MergeProto(stats.latencies()); + result.client_resources.push_back(ResourceUsage{stats.time_elapsed(), stats.time_user(), stats.time_system()}); } for (auto& client : clients) { @@ -196,10 +200,7 @@ void RunScenario(const ClientConfig& initial_client_config, size_t num_clients, GPR_ASSERT(server.stream->WritesDone()); GPR_ASSERT(server.stream->Finish().IsOk()); } - - gpr_log(GPR_INFO, "Latencies (50/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f us", - latencies.Percentile(50) / 1e3, latencies.Percentile(95) / 1e3, - latencies.Percentile(99) / 1e3, latencies.Percentile(99.9) / 1e3); -} -} + return result; } +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h index f11030a63ea..b9d2b33f651 100644 --- a/test/cpp/qps/driver.h +++ b/test/cpp/qps/driver.h @@ -34,15 +34,28 @@ #ifndef TEST_QPS_DRIVER_H #define TEST_QPS_DRIVER_H +#include "test/cpp/qps/histogram.h" #include "test/cpp/qps/qpstest.pb.h" namespace grpc { namespace testing { -void RunScenario(const grpc::testing::ClientConfig& client_config, +struct ResourceUsage { + double wall_time; + double user_time; + double system_time; +}; + +struct ScenarioResult { + Histogram latencies; + std::vector client_resources; + std::vector server_resources; +}; + +ScenarioResult RunScenario(const grpc::testing::ClientConfig& client_config, size_t num_clients, const grpc::testing::ServerConfig& server_config, size_t num_servers); -} -} +} // namespace testing +} // namespace grpc #endif diff --git a/test/cpp/qps/histogram.h b/test/cpp/qps/histogram.h index e7d10e13115..e37be80df29 100644 --- a/test/cpp/qps/histogram.h +++ b/test/cpp/qps/histogram.h @@ -43,7 +43,10 @@ namespace testing { class Histogram { public: Histogram() : impl_(gpr_histogram_create(0.01, 60e9)) {} - ~Histogram() { gpr_histogram_destroy(impl_); } + ~Histogram() { if (impl_) gpr_histogram_destroy(impl_); } + Histogram(Histogram&& other) : impl_(other.impl_) { + other.impl_ = nullptr; + } void Merge(Histogram* h) { gpr_histogram_merge(impl_, h->impl_); } void Add(double value) { gpr_histogram_add(impl_, value); } diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc index d54a6c84aac..58656b6f881 100644 --- a/test/cpp/qps/qps_driver.cc +++ b/test/cpp/qps/qps_driver.cc @@ -35,6 +35,7 @@ #include #include "test/cpp/qps/driver.h" +#include "test/cpp/qps/stats.h" DEFINE_int32(num_clients, 1, "Number of client binaries"); DEFINE_int32(num_servers, 1, "Number of server binaries"); @@ -57,6 +58,8 @@ using grpc::testing::ClientConfig; using grpc::testing::ServerConfig; using grpc::testing::ClientType; using grpc::testing::ServerType; +using grpc::testing::ResourceUsage; +using grpc::testing::sum; // In some distros, gflags is in the namespace google, and in some others, // in gflags. This hack is enabling us to find both. @@ -87,9 +90,18 @@ int main(int argc, char **argv) { server_config.set_threads(FLAGS_server_threads); server_config.set_enable_ssl(FLAGS_enable_ssl); - RunScenario(client_config, FLAGS_num_clients, server_config, + auto result = RunScenario(client_config, FLAGS_num_clients, server_config, FLAGS_num_servers); + gpr_log(GPR_INFO, "Latencies (50/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f us", + result.latencies.Percentile(50) / 1000, result.latencies.Percentile(95) / 1000, + result.latencies.Percentile(99) / 1000, result.latencies.Percentile(99.9) / 1000); + + gpr_log(GPR_INFO, "Server system time: %.2f%%", 100.0 * sum(result.server_resources, [](ResourceUsage u) { return u.system_time; }) / sum(result.server_resources, [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Server user time: %.2f%%", 100.0 * sum(result.server_resources, [](ResourceUsage u) { return u.user_time; }) / sum(result.server_resources, [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Client system time: %.2f%%", 100.0 * sum(result.client_resources, [](ResourceUsage u) { return u.system_time; }) / sum(result.client_resources, [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Client user time: %.2f%%", 100.0 * sum(result.client_resources, [](ResourceUsage u) { return u.user_time; }) / sum(result.client_resources, [](ResourceUsage u) { return u.wall_time; })); + grpc_shutdown(); return 0; } diff --git a/test/cpp/qps/stats.h b/test/cpp/qps/stats.h new file mode 100644 index 00000000000..f7a4f8c05de --- /dev/null +++ b/test/cpp/qps/stats.h @@ -0,0 +1,60 @@ +/* + * + * 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. + * + */ + +#ifndef TEST_QPS_STATS_UTILS_H +#define TEST_QPS_STATS_UTILS_H + +#include "test/cpp/qps/histogram.h" +#include + +namespace grpc { +namespace testing { + +template +double sum(const T& container, F functor) { + double r = 0; + for (auto v : container) { + r += functor(v); + } + return r; +} + +template +double average(const T& container, F functor) { + return sum(container, functor) / container.size(); +} + +} // namespace testing +} // namespace grpc + +#endif From 8856875900b6f9ae00cd5ffa311a9ed33c40c7e1 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 10:50:43 -0800 Subject: [PATCH 16/27] Async client progress --- Makefile | 2 + build.json | 1 + test/cpp/qps/client.cc | 120 ++++------------------------ test/cpp/qps/client.h | 120 +++++++++++++++++++++++++++- test/cpp/qps/client_async.cc | 149 +++++++++++++++++------------------ test/cpp/qps/qps_driver.cc | 4 + test/cpp/qps/qpstest.proto | 3 + test/cpp/qps/worker.cc | 2 +- 8 files changed, 217 insertions(+), 184 deletions(-) diff --git a/Makefile b/Makefile index a1523e2254d..36eedb95add 100644 --- a/Makefile +++ b/Makefile @@ -8179,6 +8179,7 @@ endif QPS_WORKER_SRC = \ test/cpp/qps/client.cc \ + test/cpp/qps/client_async.cc \ test/cpp/qps/server.cc \ test/cpp/qps/worker.cc \ @@ -8211,6 +8212,7 @@ endif endif $(OBJDIR)/$(CONFIG)/test/cpp/qps/client.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/qps/server.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/qps/worker.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a diff --git a/build.json b/build.json index 922e9159d16..08b1e1842c3 100644 --- a/build.json +++ b/build.json @@ -1847,6 +1847,7 @@ ], "src": [ "test/cpp/qps/client.cc", + "test/cpp/qps/client_async.cc", "test/cpp/qps/server.cc", "test/cpp/qps/worker.cc" ], diff --git a/test/cpp/qps/client.cc b/test/cpp/qps/client.cc index 877007038ef..0be01e137fb 100644 --- a/test/cpp/qps/client.cc +++ b/test/cpp/qps/client.cc @@ -63,118 +63,26 @@ namespace testing { class SynchronousClient GRPC_FINAL : public Client { public: - SynchronousClient(const ClientConfig& config) : timer_(new Timer) { - for (int i = 0; i < config.client_channels(); i++) { - channels_.push_back(ClientChannelInfo( - config.server_targets(i % config.server_targets_size()), config)); - auto* stub = channels_.back().get_stub(); - for (int j = 0; j < config.outstanding_rpcs_per_channel(); j++) { - threads_.emplace_back(new Thread(stub, config)); - } - } + SynchronousClient(const ClientConfig& config) : Client(config) { + size_t num_threads = config.outstanding_rpcs_per_channel() * config.client_channels(); + responses_.resize(num_threads); + StartThreads(num_threads); } - ClientStats Mark() { - Histogram latencies; - std::vector to_merge(threads_.size()); - for (size_t i = 0; i < threads_.size(); i++) { - threads_[i]->BeginSwap(&to_merge[i]); - } - std::unique_ptr timer(new Timer); - timer_.swap(timer); - for (size_t i = 0; i < threads_.size(); i++) { - threads_[i]->EndSwap(); - latencies.Merge(&to_merge[i]); - } - - auto timer_result = timer->Mark(); + ~SynchronousClient() { + EndThreads(); + } - ClientStats stats; - latencies.FillProto(stats.mutable_latencies()); - stats.set_time_elapsed(timer_result.wall); - stats.set_time_system(timer_result.system); - stats.set_time_user(timer_result.user); - return stats; + void ThreadFunc(Histogram* histogram, size_t thread_idx) { + auto* stub = channels_[thread_idx % channels_.size()].get_stub(); + double start = Timer::Now(); + grpc::ClientContext context; + grpc::Status s = stub->UnaryCall(&context, request_, &responses_[thread_idx]); + histogram->Add((Timer::Now() - start) * 1e9); } private: - class Thread { - public: - Thread(TestService::Stub* stub, const ClientConfig& config) - : stub_(stub), - config_(config), - done_(false), - new_(nullptr), - impl_([this]() { - SimpleRequest request; - SimpleResponse response; - request.set_response_type(grpc::testing::PayloadType::COMPRESSABLE); - request.set_response_size(config_.payload_size()); - for (;;) { - { - std::lock_guard g(mu_); - if (done_) return; - if (new_) { - new_->Swap(&histogram_); - new_ = nullptr; - cv_.notify_one(); - } - } - double start = Timer::Now(); - grpc::ClientContext context; - grpc::Status s = stub_->UnaryCall(&context, request, &response); - histogram_.Add((Timer::Now() - start) * 1e9); - } - }) {} - - ~Thread() { - { - std::lock_guard g(mu_); - done_ = true; - } - impl_.join(); - } - - void BeginSwap(Histogram* n) { - std::lock_guard g(mu_); - new_ = n; - } - - void EndSwap() { - std::unique_lock g(mu_); - cv_.wait(g, [this]() { return new_ == nullptr; }); - } - - private: - Thread(const Thread&); - Thread& operator=(const Thread&); - - TestService::Stub* stub_; - ClientConfig config_; - std::mutex mu_; - std::condition_variable cv_; - bool done_; - Histogram* new_; - Histogram histogram_; - std::thread impl_; - }; - - class ClientChannelInfo { - public: - explicit ClientChannelInfo(const grpc::string& target, - const ClientConfig& config) - : channel_(CreateTestChannel(target, config.enable_ssl())), - stub_(TestService::NewStub(channel_)) {} - ChannelInterface* get_channel() { return channel_.get(); } - TestService::Stub* get_stub() { return stub_.get(); } - - private: - std::shared_ptr channel_; - std::unique_ptr stub_; - }; - std::vector channels_; - std::vector> threads_; - std::unique_ptr timer_; + std::vector responses_; }; std::unique_ptr CreateSynchronousClient(const ClientConfig& config) { diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index 97701d3d18f..c79661c4566 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -34,6 +34,8 @@ #ifndef TEST_QPS_CLIENT_H #define TEST_QPS_CLIENT_H +#include "test/cpp/qps/histogram.h" +#include "test/cpp/qps/timer.h" #include "test/cpp/qps/qpstest.pb.h" namespace grpc { @@ -41,9 +43,125 @@ namespace testing { class Client { public: + explicit Client(const ClientConfig& config) : timer_(new Timer) { + for (int i = 0; i < config.client_channels(); i++) { + channels_.push_back(ClientChannelInfo( + config.server_targets(i % config.server_targets_size()), config)); + } + request_.set_response_type(grpc::testing::PayloadType::COMPRESSABLE); + request_.set_response_size(config.payload_size()); + } virtual ~Client() {} - virtual ClientStats Mark() = 0; + ClientStats Mark() { + Histogram latencies; + std::vector to_merge(threads_.size()); + for (size_t i = 0; i < threads_.size(); i++) { + threads_[i]->BeginSwap(&to_merge[i]); + } + std::unique_ptr timer(new Timer); + timer_.swap(timer); + for (size_t i = 0; i < threads_.size(); i++) { + threads_[i]->EndSwap(); + latencies.Merge(&to_merge[i]); + } + + auto timer_result = timer->Mark(); + + ClientStats stats; + latencies.FillProto(stats.mutable_latencies()); + stats.set_time_elapsed(timer_result.wall); + stats.set_time_system(timer_result.system); + stats.set_time_user(timer_result.user); + return stats; + } + + protected: + SimpleRequest request_; + + class ClientChannelInfo { + public: + explicit ClientChannelInfo(const grpc::string& target, + const ClientConfig& config) + : channel_(CreateTestChannel(target, config.enable_ssl())), + stub_(TestService::NewStub(channel_)) {} + ChannelInterface* get_channel() { return channel_.get(); } + TestService::Stub* get_stub() { return stub_.get(); } + + private: + std::shared_ptr channel_; + std::unique_ptr stub_; + }; + std::vector channels_; + + void StartThreads(size_t num_threads) { + for (size_t i = 0; i < num_threads; i++) { + threads_.emplace_back(new Thread(this, i)); + } + } + + void EndThreads() { + threads_.clear(); + } + + virtual void ThreadFunc(Histogram* histogram, size_t thread_idx) = 0; + + private: + class Thread { + public: + Thread(Client* client, size_t idx) + : done_(false), + new_(nullptr), + impl_([this, idx, client]() { + for (;;) { + // run the loop body + client->ThreadFunc(&histogram_, idx); + // lock, see if we're done + std::lock_guard g(mu_); + if (done_) return; + // also check if we're marking, and swap out the histogram if so + if (new_) { + new_->Swap(&histogram_); + new_ = nullptr; + cv_.notify_one(); + } + } + }) {} + + ~Thread() { + { + std::lock_guard g(mu_); + done_ = true; + } + impl_.join(); + } + + void BeginSwap(Histogram* n) { + std::lock_guard g(mu_); + new_ = n; + } + + void EndSwap() { + std::unique_lock g(mu_); + cv_.wait(g, [this]() { return new_ == nullptr; }); + } + + private: + Thread(const Thread&); + Thread& operator=(const Thread&); + + TestService::Stub* stub_; + ClientConfig config_; + std::mutex mu_; + std::condition_variable cv_; + bool done_; + Histogram* new_; + Histogram histogram_; + std::thread impl_; + }; + + std::vector> threads_; + std::unique_ptr timer_; }; std::unique_ptr CreateSynchronousClient(const ClientConfig& args); diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc index 9ea9cfe8b9b..30b85afc299 100644 --- a/test/cpp/qps/client_async.cc +++ b/test/cpp/qps/client_async.cc @@ -49,50 +49,11 @@ #include "test/core/util/grpc_profiler.h" #include "test/cpp/util/create_test_channel.h" #include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/timer.h" +#include "test/cpp/qps/client.h" -DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls."); -DEFINE_int32(server_port, 0, "Server port."); -DEFINE_string(server_host, "127.0.0.1", "Server host."); -DEFINE_int32(client_threads, 4, "Number of client threads."); - -// We have a configurable number of channels for sending RPCs. -// RPCs are sent round-robin on the available channels by the -// various threads. Interesting cases are 1 global channel or -// 1 per-thread channel, but we can support any number. -// The channels are assigned round-robin on an RPC by RPC basis -// rather than just at initialization time in order to also measure the -// impact of cache thrashing caused by channel changes. This is an issue -// if you are not in one of the above "interesting cases" -DEFINE_int32(client_channels, 4, "Number of client channels."); - -DEFINE_int32(num_rpcs, 1000, "Number of RPCs per thread."); -DEFINE_int32(payload_size, 1, "Payload size in bytes"); - -// Alternatively, specify parameters for test as a workload so that multiple -// tests are initiated back-to-back. This is convenient for keeping a borg -// allocation consistent. This is a space-separated list of -// [threads channels num_rpcs payload_size ]* -DEFINE_string(workload, "", "Workload parameters"); - -using grpc::ChannelInterface; -using grpc::CreateTestChannel; -using grpc::testing::ServerStats; -using grpc::testing::SimpleRequest; -using grpc::testing::SimpleResponse; -using grpc::testing::StatsRequest; -using grpc::testing::TestService; - -// In some distros, gflags is in the namespace google, and in some others, -// in gflags. This hack is enabling us to find both. -namespace google {} -namespace gflags {} -using namespace google; -using namespace gflags; - -static double now() { - gpr_timespec tv = gpr_now(); - return 1e9 * tv.tv_sec + tv.tv_nsec; -} +namespace grpc { +namespace testing { class ClientRpcContext { public: @@ -103,8 +64,9 @@ class ClientRpcContext { static ClientRpcContext *detag(void *t) { return reinterpret_cast(t); } - virtual void report_stats(gpr_histogram *hist) = 0; + virtual void report_stats(Histogram *hist) = 0; }; + template class ClientRpcContextUnaryImpl : public ClientRpcContext { public: @@ -113,22 +75,22 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { const RequestType &req, std::function< std::unique_ptr>( - TestService::Stub *, grpc::ClientContext *, const RequestType &, - void *)> start_req, + TestService::Stub *, grpc::ClientContext *, const RequestType &, + void *)> start_req, std::function on_done) : context_(), - stub_(stub), + stub_(stub), req_(req), response_(), next_state_(&ClientRpcContextUnaryImpl::ReqSent), callback_(on_done), - start_(now()), + start_(Timer::Now()), response_reader_( - start_req(stub_, &context_, req_, ClientRpcContext::tag(this))) {} + start_req(stub_, &context_, req_, ClientRpcContext::tag(this))) {} ~ClientRpcContextUnaryImpl() GRPC_OVERRIDE {} bool RunNextState() GRPC_OVERRIDE { return (this->*next_state_)(); } - void report_stats(gpr_histogram *hist) GRPC_OVERRIDE { - gpr_histogram_add(hist, now() - start_); + void report_stats(Histogram *hist) GRPC_OVERRIDE { + hist->Add((Timer::Now() - start_) * 1e9); } private: @@ -157,6 +119,64 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { response_reader_; }; +class AsyncClient GRPC_FINAL : public Client { + public: + explicit AsyncClient(const ClientConfig& config) : Client(config) { + for (int i = 0; i < config.async_client_threads(); i++) { + cli_cqs_.emplace_back(new CompletionQueue); + } + + auto payload_size = config.payload_size(); + auto check_done = [payload_size](grpc::Status s, SimpleResponse *response) { + GPR_ASSERT(s.IsOk() && (response->payload().type() == + grpc::testing::PayloadType::COMPRESSABLE) && + (response->payload().body().length() == + static_cast(payload_size))); + }; + + int t = 0; + for (int i = 0; i < config.outstanding_rpcs_per_channel(); i++) { + for (auto& channel : channels_) { + auto *cq = cli_cqs_[t].get(); + t = (t + 1) % cli_cqs_.size(); + auto start_req = [cq](TestService::Stub *stub, grpc::ClientContext *ctx, const SimpleRequest& request, void *tag) { + return stub->AsyncUnaryCall(ctx, request, cq, tag); + }; + + TestService::Stub* stub = channel.get_stub(); + const SimpleRequest& request = request_; + new ClientRpcContextUnaryImpl(stub, request, start_req, check_done); + } + } + + StartThreads(config.async_client_threads()); + } + + void ThreadFunc(Histogram *histogram, size_t thread_idx) { + void *got_tag; + bool ok; + cli_cqs_[thread_idx]->Next(&got_tag, &ok); + + ClientRpcContext *ctx = ClientRpcContext::detag(got_tag); + if (ctx->RunNextState() == false) { + // call the callback and then delete it + ctx->report_stats(histogram); + ctx->RunNextState(); + delete ctx; + } + } + + std::vector> cli_cqs_; +}; + +std::unique_ptr CreateAsyncClient(const ClientConfig& args) { + return std::unique_ptr(new AsyncClient(args)); +} + +} // namespace testing +} // namespace grpc + +#if 0 static void RunTest(const int client_threads, const int client_channels, const int num_rpcs, const int payload_size) { gpr_log(GPR_INFO, @@ -173,23 +193,7 @@ static void RunTest(const int client_threads, const int client_channels, std::ostringstream oss; oss << FLAGS_server_host << ":" << FLAGS_server_port; - class ClientChannelInfo { - public: - explicit ClientChannelInfo(const grpc::string &server) - : channel_(CreateTestChannel(server, FLAGS_enable_ssl)), - stub_(TestService::NewStub(channel_)) {} - ChannelInterface *get_channel() { return channel_.get(); } - TestService::Stub *get_stub() { return stub_.get(); } - - private: - std::shared_ptr channel_; - std::unique_ptr stub_; - }; - - std::vector channels; - for (int i = 0; i < client_channels; i++) { - channels.push_back(ClientChannelInfo(oss.str())); - } + std::vector threads; // Will add threads when ready to execute std::vector< ::gpr_histogram *> thread_stats(client_threads); @@ -204,12 +208,6 @@ static void RunTest(const int client_threads, const int client_channels, grpc_profiler_start("qps_client_async.prof"); - auto CheckDone = [=](grpc::Status s, SimpleResponse *response) { - GPR_ASSERT(s.IsOk() && (response->payload().type() == - grpc::testing::PayloadType::COMPRESSABLE) && - (response->payload().body().length() == - static_cast(payload_size))); - }; for (int i = 0; i < client_threads; i++) { gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); @@ -225,8 +223,6 @@ static void RunTest(const int client_threads, const int client_channels, request.set_response_size(payload_size); grpc::CompletionQueue cli_cq; - auto start_req = std::bind(&TestService::Stub::AsyncUnaryCall, _1, - _2, _3, &cli_cq, _4); int rpcs_sent = 0; while (rpcs_sent < num_rpcs) { @@ -339,3 +335,4 @@ int main(int argc, char **argv) { grpc_shutdown(); return 0; } +#endif diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc index 58656b6f881..7d73bb40d29 100644 --- a/test/cpp/qps/qps_driver.cc +++ b/test/cpp/qps/qps_driver.cc @@ -53,6 +53,7 @@ DEFINE_int32(outstanding_rpcs_per_channel, 1, DEFINE_int32(client_channels, 1, "Number of client channels"); DEFINE_int32(payload_size, 1, "Payload size"); DEFINE_string(client_type, "SYNCHRONOUS_CLIENT", "Client type"); +DEFINE_int32(async_client_threads, 1, "Async client threads"); using grpc::testing::ClientConfig; using grpc::testing::ServerConfig; @@ -84,6 +85,7 @@ int main(int argc, char **argv) { FLAGS_outstanding_rpcs_per_channel); client_config.set_client_channels(FLAGS_client_channels); client_config.set_payload_size(FLAGS_payload_size); + client_config.set_async_client_threads(FLAGS_async_client_threads); ServerConfig server_config; server_config.set_server_type(server_type); @@ -93,6 +95,8 @@ int main(int argc, char **argv) { auto result = RunScenario(client_config, FLAGS_num_clients, server_config, FLAGS_num_servers); + gpr_log(GPR_INFO, "QPS: %.1f", result.latencies.Count() / average(result.client_resources, [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Latencies (50/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f us", result.latencies.Percentile(50) / 1000, result.latencies.Percentile(95) / 1000, result.latencies.Percentile(99) / 1000, result.latencies.Percentile(99.9) / 1000); diff --git a/test/cpp/qps/qpstest.proto b/test/cpp/qps/qpstest.proto index 6543e64a014..6a7170bf580 100644 --- a/test/cpp/qps/qpstest.proto +++ b/test/cpp/qps/qpstest.proto @@ -94,8 +94,11 @@ message ClientConfig { required int32 outstanding_rpcs_per_channel = 4; required int32 client_channels = 5; required int32 payload_size = 6; + // only for async client: + optional int32 async_client_threads = 7; } +// Request current stats message Mark {} message ClientArgs { diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc index b5dbc1570db..4a2e798a477 100644 --- a/test/cpp/qps/worker.cc +++ b/test/cpp/qps/worker.cc @@ -80,7 +80,7 @@ std::unique_ptr CreateClient(const ClientConfig& config) { case ClientType::SYNCHRONOUS_CLIENT: return CreateSynchronousClient(config); case ClientType::ASYNC_CLIENT: - abort(); // return CreateAsyncClient(config); + return CreateAsyncClient(config); } abort(); } From d1e18faefcf61a184d32e5af17ceff2c2036543f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 10:51:03 -0800 Subject: [PATCH 17/27] Async client progress --- test/cpp/qps/client_async.cc | 161 ----------------------------------- 1 file changed, 161 deletions(-) diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc index 30b85afc299..4e428da1c6e 100644 --- a/test/cpp/qps/client_async.cc +++ b/test/cpp/qps/client_async.cc @@ -175,164 +175,3 @@ std::unique_ptr CreateAsyncClient(const ClientConfig& args) { } // namespace testing } // namespace grpc - -#if 0 -static void RunTest(const int client_threads, const int client_channels, - const int num_rpcs, const int payload_size) { - gpr_log(GPR_INFO, - "QPS test with parameters\n" - "enable_ssl = %d\n" - "client_channels = %d\n" - "client_threads = %d\n" - "num_rpcs = %d\n" - "payload_size = %d\n" - "server_host:server_port = %s:%d\n\n", - FLAGS_enable_ssl, client_channels, client_threads, num_rpcs, - payload_size, FLAGS_server_host.c_str(), FLAGS_server_port); - - std::ostringstream oss; - oss << FLAGS_server_host << ":" << FLAGS_server_port; - - - - std::vector threads; // Will add threads when ready to execute - std::vector< ::gpr_histogram *> thread_stats(client_threads); - - TestService::Stub *stub_stats = channels[0].get_stub(); - grpc::ClientContext context_stats_begin; - StatsRequest stats_request; - ServerStats server_stats_begin; - stats_request.set_test_num(0); - grpc::Status status_beg = stub_stats->CollectServerStats( - &context_stats_begin, stats_request, &server_stats_begin); - - grpc_profiler_start("qps_client_async.prof"); - - - for (int i = 0; i < client_threads; i++) { - gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); - GPR_ASSERT(hist != NULL); - thread_stats[i] = hist; - - threads.push_back(std::thread( - [hist, client_threads, client_channels, num_rpcs, payload_size, - &channels, &CheckDone](int channel_num) { - using namespace std::placeholders; - SimpleRequest request; - request.set_response_type(grpc::testing::PayloadType::COMPRESSABLE); - request.set_response_size(payload_size); - - grpc::CompletionQueue cli_cq; - - int rpcs_sent = 0; - while (rpcs_sent < num_rpcs) { - rpcs_sent++; - TestService::Stub *stub = channels[channel_num].get_stub(); - new ClientRpcContextUnaryImpl(stub, - request, start_req, CheckDone); - void *got_tag; - bool ok; - - // Need to call 2 next for every 1 RPC (1 for req done, 1 for resp - // done) - cli_cq.Next(&got_tag, &ok); - if (!ok) break; - ClientRpcContext *ctx = ClientRpcContext::detag(got_tag); - if (ctx->RunNextState() == false) { - // call the callback and then delete it - ctx->report_stats(hist); - ctx->RunNextState(); - delete ctx; - } - cli_cq.Next(&got_tag, &ok); - if (!ok) break; - ctx = ClientRpcContext::detag(got_tag); - if (ctx->RunNextState() == false) { - // call the callback and then delete it - ctx->report_stats(hist); - ctx->RunNextState(); - delete ctx; - } - // Now do runtime round-robin assignment of the next - // channel number - channel_num += client_threads; - channel_num %= client_channels; - } - }, - i % client_channels)); - } - - gpr_histogram *hist = gpr_histogram_create(0.01, 60e9); - GPR_ASSERT(hist != NULL); - for (auto &t : threads) { - t.join(); - } - - grpc_profiler_stop(); - - for (int i = 0; i < client_threads; i++) { - gpr_histogram *h = thread_stats[i]; - gpr_log(GPR_INFO, "latency at thread %d (50/90/95/99/99.9): %f/%f/%f/%f/%f", - i, gpr_histogram_percentile(h, 50), gpr_histogram_percentile(h, 90), - gpr_histogram_percentile(h, 95), gpr_histogram_percentile(h, 99), - gpr_histogram_percentile(h, 99.9)); - gpr_histogram_merge(hist, h); - gpr_histogram_destroy(h); - } - - gpr_log( - GPR_INFO, - "latency across %d threads with %d channels and %d payload " - "(50/90/95/99/99.9): %f / %f / %f / %f / %f", - client_threads, client_channels, payload_size, - gpr_histogram_percentile(hist, 50), gpr_histogram_percentile(hist, 90), - gpr_histogram_percentile(hist, 95), gpr_histogram_percentile(hist, 99), - gpr_histogram_percentile(hist, 99.9)); - gpr_histogram_destroy(hist); - - grpc::ClientContext context_stats_end; - ServerStats server_stats_end; - grpc::Status status_end = stub_stats->CollectServerStats( - &context_stats_end, stats_request, &server_stats_end); - - double elapsed = server_stats_end.time_now() - server_stats_begin.time_now(); - int total_rpcs = client_threads * num_rpcs; - double utime = server_stats_end.time_user() - server_stats_begin.time_user(); - double stime = - server_stats_end.time_system() - server_stats_begin.time_system(); - gpr_log(GPR_INFO, - "Elapsed time: %.3f\n" - "RPC Count: %d\n" - "QPS: %.3f\n" - "System time: %.3f\n" - "User time: %.3f\n" - "Resource usage: %.1f%%\n", - elapsed, total_rpcs, total_rpcs / elapsed, stime, utime, - (stime + utime) / elapsed * 100.0); -} - -int main(int argc, char **argv) { - grpc_init(); - ParseCommandLineFlags(&argc, &argv, true); - - GPR_ASSERT(FLAGS_server_port); - - if (FLAGS_workload.length() == 0) { - RunTest(FLAGS_client_threads, FLAGS_client_channels, FLAGS_num_rpcs, - FLAGS_payload_size); - } else { - std::istringstream workload(FLAGS_workload); - int client_threads, client_channels, num_rpcs, payload_size; - workload >> client_threads; - while (!workload.eof()) { - workload >> client_channels >> num_rpcs >> payload_size; - RunTest(client_threads, client_channels, num_rpcs, payload_size); - workload >> client_threads; - } - gpr_log(GPR_INFO, "Done with specified workload."); - } - - grpc_shutdown(); - return 0; -} -#endif From e38ec2112270301b6aa10dc62dcfd51954cfd587 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 11:19:15 -0800 Subject: [PATCH 18/27] Linux compile fix --- test/cpp/qps/client.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index c79661c4566..c2fdbb576fa 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -38,6 +38,9 @@ #include "test/cpp/qps/timer.h" #include "test/cpp/qps/qpstest.pb.h" +#include +#include + namespace grpc { namespace testing { From ef6383904280e5606cbf6b5f71a534b1da17e956 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 12:23:12 -0800 Subject: [PATCH 19/27] Async client works --- test/cpp/qps/client_async.cc | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc index 4e428da1c6e..cd80f1f9a95 100644 --- a/test/cpp/qps/client_async.cc +++ b/test/cpp/qps/client_async.cc @@ -60,6 +60,7 @@ class ClientRpcContext { ClientRpcContext() {} virtual ~ClientRpcContext() {} virtual bool RunNextState() = 0; // do next state, return false if steps done + virtual void StartNewClone() = 0; static void *tag(ClientRpcContext *c) { return reinterpret_cast(c); } static ClientRpcContext *detag(void *t) { return reinterpret_cast(t); @@ -83,7 +84,7 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { req_(req), response_(), next_state_(&ClientRpcContextUnaryImpl::ReqSent), - callback_(on_done), + callback_(on_done), start_req_(start_req), start_(Timer::Now()), response_reader_( start_req(stub_, &context_, req_, ClientRpcContext::tag(this))) {} @@ -93,6 +94,10 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { hist->Add((Timer::Now() - start_) * 1e9); } + void StartNewClone() { + new ClientRpcContextUnaryImpl(stub_, req_, start_req_, callback_); + } + private: bool ReqSent() { next_state_ = &ClientRpcContextUnaryImpl::RespDone; @@ -113,6 +118,10 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { ResponseType response_; bool (ClientRpcContextUnaryImpl::*next_state_)(); std::function callback_; + std::function< + std::unique_ptr>( + TestService::Stub *, grpc::ClientContext *, const RequestType &, + void *)> start_req_; grpc::Status status_; double start_; std::unique_ptr> @@ -152,6 +161,19 @@ class AsyncClient GRPC_FINAL : public Client { StartThreads(config.async_client_threads()); } + ~AsyncClient() GRPC_OVERRIDE { + EndThreads(); + + for (auto& cq : cli_cqs_) { + cq->Shutdown(); + void *got_tag; + bool ok; + while (cq->Next(&got_tag, &ok)) { + delete ClientRpcContext::detag(got_tag); + } + } + } + void ThreadFunc(Histogram *histogram, size_t thread_idx) { void *got_tag; bool ok; @@ -162,6 +184,7 @@ class AsyncClient GRPC_FINAL : public Client { // call the callback and then delete it ctx->report_stats(histogram); ctx->RunNextState(); + ctx->StartNewClone(); delete ctx; } } From d6479d6cc42ca180bcfc219751cf2a6f73f87dd4 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 12:50:11 -0800 Subject: [PATCH 20/27] Async server works --- Makefile | 2 + build.json | 1 + test/cpp/qps/server.cc | 31 +------- test/cpp/qps/server.h | 30 +++++++- test/cpp/qps/server_async.cc | 140 ++++++----------------------------- test/cpp/qps/worker.cc | 2 +- 6 files changed, 58 insertions(+), 148 deletions(-) diff --git a/Makefile b/Makefile index 36eedb95add..aef6ff3a639 100644 --- a/Makefile +++ b/Makefile @@ -8181,6 +8181,7 @@ QPS_WORKER_SRC = \ test/cpp/qps/client.cc \ test/cpp/qps/client_async.cc \ test/cpp/qps/server.cc \ + test/cpp/qps/server_async.cc \ test/cpp/qps/worker.cc \ QPS_WORKER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_WORKER_SRC)))) @@ -8214,6 +8215,7 @@ endif $(OBJDIR)/$(CONFIG)/test/cpp/qps/client.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/qps/server.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/qps/worker.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_qps_worker: $(QPS_WORKER_OBJS:.o=.dep) diff --git a/build.json b/build.json index 08b1e1842c3..a8dc2e6bec5 100644 --- a/build.json +++ b/build.json @@ -1849,6 +1849,7 @@ "test/cpp/qps/client.cc", "test/cpp/qps/client_async.cc", "test/cpp/qps/server.cc", + "test/cpp/qps/server_async.cc", "test/cpp/qps/worker.cc" ], "deps": [ diff --git a/test/cpp/qps/server.cc b/test/cpp/qps/server.cc index 8424dbafe97..e598fb51ae0 100644 --- a/test/cpp/qps/server.cc +++ b/test/cpp/qps/server.cc @@ -57,24 +57,12 @@ namespace grpc { namespace testing { -static bool SetPayload(PayloadType type, int size, Payload* payload) { - PayloadType response_type = type; - // TODO(yangg): Support UNCOMPRESSABLE payload. - if (type != PayloadType::COMPRESSABLE) { - return false; - } - payload->set_type(response_type); - std::unique_ptr body(new char[size]()); - payload->set_body(body.get(), size); - return true; -} - class TestServiceImpl GRPC_FINAL : public TestService::Service { public: Status UnaryCall(ServerContext* context, const SimpleRequest* request, SimpleResponse* response) override { if (request->has_response_size() && request->response_size() > 0) { - if (!SetPayload(request->response_type(), request->response_size(), + if (!Server::SetPayload(request->response_type(), request->response_size(), response->mutable_payload())) { return Status(grpc::StatusCode::INTERNAL, "Error creating payload."); } @@ -87,21 +75,7 @@ class SynchronousServer GRPC_FINAL : public grpc::testing::Server { public: SynchronousServer(const ServerConfig& config, int port) : thread_pool_(config.threads()), - impl_(MakeImpl(port)), - timer_(new Timer) {} - - ServerStats Mark() GRPC_OVERRIDE { - std::unique_ptr timer(new Timer); - timer.swap(timer_); - - auto timer_result = timer->Mark(); - - ServerStats stats; - stats.set_time_elapsed(timer_result.wall); - stats.set_time_system(timer_result.system); - stats.set_time_user(timer_result.user); - return stats; - } + impl_(MakeImpl(port)) {} private: std::unique_ptr MakeImpl(int port) { @@ -120,7 +94,6 @@ class SynchronousServer GRPC_FINAL : public grpc::testing::Server { TestServiceImpl service_; ThreadPool thread_pool_; std::unique_ptr impl_; - std::unique_ptr timer_; }; std::unique_ptr CreateSynchronousServer( diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h index 3542c17a6a2..ca22d7ca1cd 100644 --- a/test/cpp/qps/server.h +++ b/test/cpp/qps/server.h @@ -34,6 +34,7 @@ #ifndef TEST_QPS_SERVER_H #define TEST_QPS_SERVER_H +#include "test/cpp/qps/timer.h" #include "test/cpp/qps/qpstest.pb.h" namespace grpc { @@ -41,9 +42,36 @@ namespace testing { class Server { public: + Server():timer_(new Timer) {} virtual ~Server() {} - virtual ServerStats Mark() = 0; + ServerStats Mark() { + std::unique_ptr timer(new Timer); + timer.swap(timer_); + + auto timer_result = timer->Mark(); + + ServerStats stats; + stats.set_time_elapsed(timer_result.wall); + stats.set_time_system(timer_result.system); + stats.set_time_user(timer_result.user); + return stats; + } + + static bool SetPayload(PayloadType type, int size, Payload* payload) { + PayloadType response_type = type; + // TODO(yangg): Support UNCOMPRESSABLE payload. + if (type != PayloadType::COMPRESSABLE) { + return false; + } + payload->set_type(response_type); + std::unique_ptr body(new char[size]()); + payload->set_body(body.get(), size); + return true; + } + + private: + std::unique_ptr timer_; }; std::unique_ptr CreateSynchronousServer(const ServerConfig& config, diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index c006262fc34..741a85802ad 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -51,104 +51,37 @@ #include "src/cpp/server/thread_pool.h" #include "test/core/util/grpc_profiler.h" #include "test/cpp/qps/qpstest.pb.h" +#include "test/cpp/qps/server.h" #include #include -DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls."); -DEFINE_int32(port, 0, "Server port."); -DEFINE_int32(server_threads, 4, "Number of server threads."); +namespace grpc { + namespace testing { -using grpc::CompletionQueue; -using grpc::Server; -using grpc::ServerBuilder; -using grpc::ServerContext; -using grpc::ThreadPool; -using grpc::testing::Payload; -using grpc::testing::PayloadType; -using grpc::testing::ServerStats; -using grpc::testing::SimpleRequest; -using grpc::testing::SimpleResponse; -using grpc::testing::StatsRequest; -using grpc::testing::TestService; -using grpc::Status; - -// In some distros, gflags is in the namespace google, and in some others, -// in gflags. This hack is enabling us to find both. -namespace google {} -namespace gflags {} -using namespace google; -using namespace gflags; - -static bool got_sigint = false; - -static void sigint_handler(int x) { got_sigint = 1; } - -static double time_double(struct timeval *tv) { - return tv->tv_sec + 1e-6 * tv->tv_usec; -} - -static bool SetPayload(PayloadType type, int size, Payload *payload) { - PayloadType response_type = type; - // TODO(yangg): Support UNCOMPRESSABLE payload. - if (type != PayloadType::COMPRESSABLE) { - return false; - } - payload->set_type(response_type); - std::unique_ptr body(new char[size]()); - payload->set_body(body.get(), size); - return true; -} - -namespace { - -class AsyncQpsServerTest { +class AsyncQpsServerTest : public Server { public: - AsyncQpsServerTest() : srv_cq_(), async_service_(&srv_cq_), server_(nullptr) { + AsyncQpsServerTest(const ServerConfig& config, int port) : srv_cq_(), async_service_(&srv_cq_), server_(nullptr) { char *server_address = NULL; - gpr_join_host_port(&server_address, "::", FLAGS_port); + gpr_join_host_port(&server_address, "::", port); ServerBuilder builder; builder.AddPort(server_address); + gpr_free(server_address); builder.RegisterAsyncService(&async_service_); server_ = builder.BuildAndStart(); - gpr_log(GPR_INFO, "Server listening on %s\n", server_address); - gpr_free(server_address); using namespace std::placeholders; request_unary_ = std::bind(&TestService::AsyncService::RequestUnaryCall, &async_service_, _1, _2, _3, &srv_cq_, _4); - request_stats_ = - std::bind(&TestService::AsyncService::RequestCollectServerStats, - &async_service_, _1, _2, _3, &srv_cq_, _4); for (int i = 0; i < 100; i++) { contexts_.push_front( new ServerRpcContextUnaryImpl( request_unary_, UnaryCall)); - contexts_.push_front( - new ServerRpcContextUnaryImpl( - request_stats_, CollectServerStats)); - } - } - ~AsyncQpsServerTest() { - server_->Shutdown(); - void *ignored_tag; - bool ignored_ok; - srv_cq_.Shutdown(); - while (srv_cq_.Next(&ignored_tag, &ignored_ok)) { } - while (!contexts_.empty()) { - delete contexts_.front(); - contexts_.pop_front(); - } - for (auto& thr: threads_) { - thr.join(); - } - } - void ServeRpcs(int num_threads) { - for (int i = 0; i < num_threads; i++) { + for (int i = 0; i < config.threads(); i++) { threads_.push_back(std::thread([=]() { // Wait until work is available or we are shutting down bool ok; @@ -166,8 +99,16 @@ class AsyncQpsServerTest { return; })); } - while (!got_sigint) { - std::this_thread::sleep_for(std::chrono::seconds(5)); + } + ~AsyncQpsServerTest() { + server_->Shutdown(); + srv_cq_.Shutdown(); + for (auto& thr: threads_) { + thr.join(); + } + while (!contexts_.empty()) { + delete contexts_.front(); + contexts_.pop_front(); } } @@ -240,17 +181,6 @@ class AsyncQpsServerTest { grpc::ServerAsyncResponseWriter response_writer_; }; - static Status CollectServerStats(const StatsRequest *, - ServerStats *response) { - struct rusage usage; - struct timeval tv; - gettimeofday(&tv, NULL); - getrusage(RUSAGE_SELF, &usage); - response->set_time_now(time_double(&tv)); - response->set_time_user(time_double(&usage.ru_utime)); - response->set_time_system(time_double(&usage.ru_stime)); - return Status::OK; - } static Status UnaryCall(const SimpleRequest *request, SimpleResponse *response) { if (request->has_response_size() && request->response_size() > 0) { @@ -264,40 +194,16 @@ class AsyncQpsServerTest { CompletionQueue srv_cq_; TestService::AsyncService async_service_; std::vector threads_; - std::unique_ptr server_; + std::unique_ptr server_; std::function *, void *)> request_unary_; - std::function *, void *)> - request_stats_; std::forward_list contexts_; }; -} // namespace - -static void RunServer() { - AsyncQpsServerTest server; - - grpc_profiler_start("qps_server_async.prof"); - - server.ServeRpcs(FLAGS_server_threads); - - grpc_profiler_stop(); +std::unique_ptr CreateAsyncServer(const ServerConfig& config, int port) { + return std::unique_ptr(new AsyncQpsServerTest(config, port)); } -int main(int argc, char **argv) { - grpc_init(); - ParseCommandLineFlags(&argc, &argv, true); - GPR_ASSERT(FLAGS_port != 0); - GPR_ASSERT(!FLAGS_enable_ssl); - - signal(SIGINT, sigint_handler); - - RunServer(); - - grpc_shutdown(); - google::protobuf::ShutdownProtobufLibrary(); - - return 0; -} + }// namespace testing +}// namespace grpc diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc index 4a2e798a477..a8d5752120d 100644 --- a/test/cpp/qps/worker.cc +++ b/test/cpp/qps/worker.cc @@ -90,7 +90,7 @@ std::unique_ptr CreateServer(const ServerConfig& config) { case ServerType::SYNCHRONOUS_SERVER: return CreateSynchronousServer(config, FLAGS_server_port); case ServerType::ASYNC_SERVER: - abort(); // return CreateAsyncServer(config, FLAGS_server_port); + return CreateAsyncServer(config, FLAGS_server_port); } abort(); } From a8dc37a2dd607015c3c32c1aaa49b893bd160f73 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 12:56:00 -0800 Subject: [PATCH 21/27] Rename some files --- Makefile | 8 ++++---- build.json | 4 ++-- test/cpp/qps/{client.cc => client_sync.cc} | 0 test/cpp/qps/{server.cc => server_sync.cc} | 0 4 files changed, 6 insertions(+), 6 deletions(-) rename test/cpp/qps/{client.cc => client_sync.cc} (100%) rename test/cpp/qps/{server.cc => server_sync.cc} (100%) diff --git a/Makefile b/Makefile index aef6ff3a639..186aec6b82b 100644 --- a/Makefile +++ b/Makefile @@ -8178,10 +8178,10 @@ endif QPS_WORKER_SRC = \ - test/cpp/qps/client.cc \ test/cpp/qps/client_async.cc \ - test/cpp/qps/server.cc \ + test/cpp/qps/client_sync.cc \ test/cpp/qps/server_async.cc \ + test/cpp/qps/server_sync.cc \ test/cpp/qps/worker.cc \ QPS_WORKER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(QPS_WORKER_SRC)))) @@ -8212,10 +8212,10 @@ endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/qps/client.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -$(OBJDIR)/$(CONFIG)/test/cpp/qps/server.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_sync.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_sync.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OBJDIR)/$(CONFIG)/test/cpp/qps/worker.o: $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_qps_worker: $(QPS_WORKER_OBJS:.o=.dep) diff --git a/build.json b/build.json index a8dc2e6bec5..fdf87f311d9 100644 --- a/build.json +++ b/build.json @@ -1846,10 +1846,10 @@ "test/cpp/qps/server.h" ], "src": [ - "test/cpp/qps/client.cc", "test/cpp/qps/client_async.cc", - "test/cpp/qps/server.cc", + "test/cpp/qps/client_sync.cc", "test/cpp/qps/server_async.cc", + "test/cpp/qps/server_sync.cc", "test/cpp/qps/worker.cc" ], "deps": [ diff --git a/test/cpp/qps/client.cc b/test/cpp/qps/client_sync.cc similarity index 100% rename from test/cpp/qps/client.cc rename to test/cpp/qps/client_sync.cc diff --git a/test/cpp/qps/server.cc b/test/cpp/qps/server_sync.cc similarity index 100% rename from test/cpp/qps/server.cc rename to test/cpp/qps/server_sync.cc From c98bef7303b0b626879b8db88e22249c8a6faa24 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 13:01:21 -0800 Subject: [PATCH 22/27] Compile fix --- test/cpp/qps/worker.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc index a8d5752120d..ae5f3658e00 100644 --- a/test/cpp/qps/worker.cc +++ b/test/cpp/qps/worker.cc @@ -70,8 +70,6 @@ using namespace gflags; static bool got_sigint = false; -static void sigint_handler(int x) { got_sigint = 1; } - namespace grpc { namespace testing { From 50a976f56c96dc0af5be9c5fc769d5d3fb2ab039 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 13:40:52 -0800 Subject: [PATCH 23/27] Linux compile fix --- test/cpp/qps/worker.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc index ae5f3658e00..45b8b6dd9a9 100644 --- a/test/cpp/qps/worker.cc +++ b/test/cpp/qps/worker.cc @@ -225,8 +225,6 @@ static void RunServer() { } // namespace grpc int main(int argc, char** argv) { - signal(SIGINT, sigint_handler); - grpc_init(); ParseCommandLineFlags(&argc, &argv, true); From a182bf12b0ef71e6fdcb93a818c4476a9d142e37 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 13:54:39 -0800 Subject: [PATCH 24/27] clang-format --- test/cpp/qps/client.h | 13 +++++------- test/cpp/qps/client_async.cc | 41 ++++++++++++++++++------------------ test/cpp/qps/client_sync.cc | 10 ++++----- test/cpp/qps/driver.cc | 12 +++++++---- test/cpp/qps/driver.h | 10 ++++----- test/cpp/qps/histogram.h | 6 +++--- test/cpp/qps/qps_driver.cc | 39 ++++++++++++++++++++++++++-------- test/cpp/qps/server.h | 24 ++++++++++----------- test/cpp/qps/server_async.cc | 20 ++++++++++-------- test/cpp/qps/server_sync.cc | 8 +++---- test/cpp/qps/stats.h | 6 +++--- 11 files changed, 107 insertions(+), 82 deletions(-) diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h index c2fdbb576fa..221fb30fc59 100644 --- a/test/cpp/qps/client.h +++ b/test/cpp/qps/client.h @@ -84,8 +84,7 @@ class Client { class ClientChannelInfo { public: - explicit ClientChannelInfo(const grpc::string& target, - const ClientConfig& config) + ClientChannelInfo(const grpc::string& target, const ClientConfig& config) : channel_(CreateTestChannel(target, config.enable_ssl())), stub_(TestService::NewStub(channel_)) {} ChannelInterface* get_channel() { return channel_.get(); } @@ -98,14 +97,12 @@ class Client { std::vector channels_; void StartThreads(size_t num_threads) { - for (size_t i = 0; i < num_threads; i++) { - threads_.emplace_back(new Thread(this, i)); - } + for (size_t i = 0; i < num_threads; i++) { + threads_.emplace_back(new Thread(this, i)); + } } - void EndThreads() { - threads_.clear(); - } + void EndThreads() { threads_.clear(); } virtual void ThreadFunc(Histogram* histogram, size_t thread_idx) = 0; diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc index cd80f1f9a95..5eb9ff6521f 100644 --- a/test/cpp/qps/client_async.cc +++ b/test/cpp/qps/client_async.cc @@ -72,22 +72,22 @@ template class ClientRpcContextUnaryImpl : public ClientRpcContext { public: ClientRpcContextUnaryImpl( - TestService::Stub *stub, - const RequestType &req, + TestService::Stub *stub, const RequestType &req, std::function< std::unique_ptr>( - TestService::Stub *, grpc::ClientContext *, const RequestType &, - void *)> start_req, + TestService::Stub *, grpc::ClientContext *, const RequestType &, + void *)> start_req, std::function on_done) : context_(), stub_(stub), req_(req), response_(), next_state_(&ClientRpcContextUnaryImpl::ReqSent), - callback_(on_done), start_req_(start_req), + callback_(on_done), + start_req_(start_req), start_(Timer::Now()), response_reader_( - start_req(stub_, &context_, req_, ClientRpcContext::tag(this))) {} + start_req(stub_, &context_, req_, ClientRpcContext::tag(this))) {} ~ClientRpcContextUnaryImpl() GRPC_OVERRIDE {} bool RunNextState() GRPC_OVERRIDE { return (this->*next_state_)(); } void report_stats(Histogram *hist) GRPC_OVERRIDE { @@ -118,10 +118,9 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { ResponseType response_; bool (ClientRpcContextUnaryImpl::*next_state_)(); std::function callback_; - std::function< - std::unique_ptr>( - TestService::Stub *, grpc::ClientContext *, const RequestType &, - void *)> start_req_; + std::function>( + TestService::Stub *, grpc::ClientContext *, const RequestType &, void *)> + start_req_; grpc::Status status_; double start_; std::unique_ptr> @@ -130,7 +129,7 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { class AsyncClient GRPC_FINAL : public Client { public: - explicit AsyncClient(const ClientConfig& config) : Client(config) { + explicit AsyncClient(const ClientConfig &config) : Client(config) { for (int i = 0; i < config.async_client_threads(); i++) { cli_cqs_.emplace_back(new CompletionQueue); } @@ -145,16 +144,18 @@ class AsyncClient GRPC_FINAL : public Client { int t = 0; for (int i = 0; i < config.outstanding_rpcs_per_channel(); i++) { - for (auto& channel : channels_) { + for (auto &channel : channels_) { auto *cq = cli_cqs_[t].get(); t = (t + 1) % cli_cqs_.size(); - auto start_req = [cq](TestService::Stub *stub, grpc::ClientContext *ctx, const SimpleRequest& request, void *tag) { + auto start_req = [cq](TestService::Stub *stub, grpc::ClientContext *ctx, + const SimpleRequest &request, void *tag) { return stub->AsyncUnaryCall(ctx, request, cq, tag); }; - TestService::Stub* stub = channel.get_stub(); - const SimpleRequest& request = request_; - new ClientRpcContextUnaryImpl(stub, request, start_req, check_done); + TestService::Stub *stub = channel.get_stub(); + const SimpleRequest &request = request_; + new ClientRpcContextUnaryImpl( + stub, request, start_req, check_done); } } @@ -164,7 +165,7 @@ class AsyncClient GRPC_FINAL : public Client { ~AsyncClient() GRPC_OVERRIDE { EndThreads(); - for (auto& cq : cli_cqs_) { + for (auto &cq : cli_cqs_) { cq->Shutdown(); void *got_tag; bool ok; @@ -192,9 +193,9 @@ class AsyncClient GRPC_FINAL : public Client { std::vector> cli_cqs_; }; -std::unique_ptr CreateAsyncClient(const ClientConfig& args) { +std::unique_ptr CreateAsyncClient(const ClientConfig &args) { return std::unique_ptr(new AsyncClient(args)); } -} // namespace testing -} // namespace grpc +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc index 0be01e137fb..7bb7231c6f6 100644 --- a/test/cpp/qps/client_sync.cc +++ b/test/cpp/qps/client_sync.cc @@ -64,20 +64,20 @@ namespace testing { class SynchronousClient GRPC_FINAL : public Client { public: SynchronousClient(const ClientConfig& config) : Client(config) { - size_t num_threads = config.outstanding_rpcs_per_channel() * config.client_channels(); + size_t num_threads = + config.outstanding_rpcs_per_channel() * config.client_channels(); responses_.resize(num_threads); StartThreads(num_threads); } - ~SynchronousClient() { - EndThreads(); - } + ~SynchronousClient() { EndThreads(); } void ThreadFunc(Histogram* histogram, size_t thread_idx) { auto* stub = channels_[thread_idx % channels_.size()].get_stub(); double start = Timer::Now(); grpc::ClientContext context; - grpc::Status s = stub->UnaryCall(&context, request_, &responses_[thread_idx]); + grpc::Status s = + stub->UnaryCall(&context, request_, &responses_[thread_idx]); histogram->Add((Timer::Now() - start) * 1e9); } diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index de1ccce3d72..6d5df799a27 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -71,8 +71,10 @@ static vector get_hosts(const string& name) { } } -ScenarioResult RunScenario(const ClientConfig& initial_client_config, size_t num_clients, - const ServerConfig& server_config, size_t num_servers) { +ScenarioResult RunScenario(const ClientConfig& initial_client_config, + size_t num_clients, + const ServerConfig& server_config, + size_t num_servers) { // ClientContext allocator (all are destroyed at scope exit) list contexts; auto alloc_context = [&contexts]() { @@ -183,13 +185,15 @@ ScenarioResult RunScenario(const ClientConfig& initial_client_config, size_t num for (auto& server : servers) { GPR_ASSERT(server.stream->Read(&server_status)); const auto& stats = server_status.stats(); - result.server_resources.push_back(ResourceUsage{stats.time_elapsed(), stats.time_user(), stats.time_system()}); + result.server_resources.push_back(ResourceUsage{ + stats.time_elapsed(), stats.time_user(), stats.time_system()}); } for (auto& client : clients) { GPR_ASSERT(client.stream->Read(&client_status)); const auto& stats = client_status.stats(); result.latencies.MergeProto(stats.latencies()); - result.client_resources.push_back(ResourceUsage{stats.time_elapsed(), stats.time_user(), stats.time_system()}); + result.client_resources.push_back(ResourceUsage{ + stats.time_elapsed(), stats.time_user(), stats.time_system()}); } for (auto& client : clients) { diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h index b9d2b33f651..d87e80dc552 100644 --- a/test/cpp/qps/driver.h +++ b/test/cpp/qps/driver.h @@ -52,10 +52,10 @@ struct ScenarioResult { }; ScenarioResult RunScenario(const grpc::testing::ClientConfig& client_config, - size_t num_clients, - const grpc::testing::ServerConfig& server_config, - size_t num_servers); -} // namespace testing -} // namespace grpc + size_t num_clients, + const grpc::testing::ServerConfig& server_config, + size_t num_servers); +} // namespace testing +} // namespace grpc #endif diff --git a/test/cpp/qps/histogram.h b/test/cpp/qps/histogram.h index e37be80df29..7ba00e94c39 100644 --- a/test/cpp/qps/histogram.h +++ b/test/cpp/qps/histogram.h @@ -43,10 +43,10 @@ namespace testing { class Histogram { public: Histogram() : impl_(gpr_histogram_create(0.01, 60e9)) {} - ~Histogram() { if (impl_) gpr_histogram_destroy(impl_); } - Histogram(Histogram&& other) : impl_(other.impl_) { - other.impl_ = nullptr; + ~Histogram() { + if (impl_) gpr_histogram_destroy(impl_); } + Histogram(Histogram&& other) : impl_(other.impl_) { other.impl_ = nullptr; } void Merge(Histogram* h) { gpr_histogram_merge(impl_, h->impl_); } void Add(double value) { gpr_histogram_add(impl_, value); } diff --git a/test/cpp/qps/qps_driver.cc b/test/cpp/qps/qps_driver.cc index 7d73bb40d29..bf51e7408e9 100644 --- a/test/cpp/qps/qps_driver.cc +++ b/test/cpp/qps/qps_driver.cc @@ -93,18 +93,39 @@ int main(int argc, char **argv) { server_config.set_enable_ssl(FLAGS_enable_ssl); auto result = RunScenario(client_config, FLAGS_num_clients, server_config, - FLAGS_num_servers); + FLAGS_num_servers); - gpr_log(GPR_INFO, "QPS: %.1f", result.latencies.Count() / average(result.client_resources, [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "QPS: %.1f", + result.latencies.Count() / + average(result.client_resources, + [](ResourceUsage u) { return u.wall_time; })); gpr_log(GPR_INFO, "Latencies (50/95/99/99.9%%-ile): %.1f/%.1f/%.1f/%.1f us", - result.latencies.Percentile(50) / 1000, result.latencies.Percentile(95) / 1000, - result.latencies.Percentile(99) / 1000, result.latencies.Percentile(99.9) / 1000); - - gpr_log(GPR_INFO, "Server system time: %.2f%%", 100.0 * sum(result.server_resources, [](ResourceUsage u) { return u.system_time; }) / sum(result.server_resources, [](ResourceUsage u) { return u.wall_time; })); - gpr_log(GPR_INFO, "Server user time: %.2f%%", 100.0 * sum(result.server_resources, [](ResourceUsage u) { return u.user_time; }) / sum(result.server_resources, [](ResourceUsage u) { return u.wall_time; })); - gpr_log(GPR_INFO, "Client system time: %.2f%%", 100.0 * sum(result.client_resources, [](ResourceUsage u) { return u.system_time; }) / sum(result.client_resources, [](ResourceUsage u) { return u.wall_time; })); - gpr_log(GPR_INFO, "Client user time: %.2f%%", 100.0 * sum(result.client_resources, [](ResourceUsage u) { return u.user_time; }) / sum(result.client_resources, [](ResourceUsage u) { return u.wall_time; })); + result.latencies.Percentile(50) / 1000, + result.latencies.Percentile(95) / 1000, + result.latencies.Percentile(99) / 1000, + result.latencies.Percentile(99.9) / 1000); + + gpr_log(GPR_INFO, "Server system time: %.2f%%", + 100.0 * sum(result.server_resources, + [](ResourceUsage u) { return u.system_time; }) / + sum(result.server_resources, + [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Server user time: %.2f%%", + 100.0 * sum(result.server_resources, + [](ResourceUsage u) { return u.user_time; }) / + sum(result.server_resources, + [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Client system time: %.2f%%", + 100.0 * sum(result.client_resources, + [](ResourceUsage u) { return u.system_time; }) / + sum(result.client_resources, + [](ResourceUsage u) { return u.wall_time; })); + gpr_log(GPR_INFO, "Client user time: %.2f%%", + 100.0 * sum(result.client_resources, + [](ResourceUsage u) { return u.user_time; }) / + sum(result.client_resources, + [](ResourceUsage u) { return u.wall_time; })); grpc_shutdown(); return 0; diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h index ca22d7ca1cd..ef71cb94d00 100644 --- a/test/cpp/qps/server.h +++ b/test/cpp/qps/server.h @@ -42,7 +42,7 @@ namespace testing { class Server { public: - Server():timer_(new Timer) {} + Server() : timer_(new Timer) {} virtual ~Server() {} ServerStats Mark() { @@ -58,17 +58,17 @@ class Server { return stats; } - static bool SetPayload(PayloadType type, int size, Payload* payload) { - PayloadType response_type = type; - // TODO(yangg): Support UNCOMPRESSABLE payload. - if (type != PayloadType::COMPRESSABLE) { - return false; - } - payload->set_type(response_type); - std::unique_ptr body(new char[size]()); - payload->set_body(body.get(), size); - return true; - } + static bool SetPayload(PayloadType type, int size, Payload* payload) { + PayloadType response_type = type; + // TODO(yangg): Support UNCOMPRESSABLE payload. + if (type != PayloadType::COMPRESSABLE) { + return false; + } + payload->set_type(response_type); + std::unique_ptr body(new char[size]()); + payload->set_body(body.get(), size); + return true; + } private: std::unique_ptr timer_; diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index 741a85802ad..64aca957e4c 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -57,11 +57,12 @@ #include namespace grpc { - namespace testing { +namespace testing { class AsyncQpsServerTest : public Server { public: - AsyncQpsServerTest(const ServerConfig& config, int port) : srv_cq_(), async_service_(&srv_cq_), server_(nullptr) { + AsyncQpsServerTest(const ServerConfig &config, int port) + : srv_cq_(), async_service_(&srv_cq_), server_(nullptr) { char *server_address = NULL; gpr_join_host_port(&server_address, "::", port); @@ -103,7 +104,7 @@ class AsyncQpsServerTest : public Server { ~AsyncQpsServerTest() { server_->Shutdown(); srv_cq_.Shutdown(); - for (auto& thr: threads_) { + for (auto &thr : threads_) { thr.join(); } while (!contexts_.empty()) { @@ -117,8 +118,8 @@ class AsyncQpsServerTest : public Server { public: ServerRpcContext() {} virtual ~ServerRpcContext(){}; - virtual bool RunNextState() = 0;// do next state, return false if all done - virtual void Reset() = 0; // start this back at a clean state + virtual bool RunNextState() = 0; // do next state, return false if all done + virtual void Reset() = 0; // start this back at a clean state }; static void *tag(ServerRpcContext *func) { return reinterpret_cast(func); @@ -201,9 +202,10 @@ class AsyncQpsServerTest : public Server { std::forward_list contexts_; }; -std::unique_ptr CreateAsyncServer(const ServerConfig& config, int port) { - return std::unique_ptr(new AsyncQpsServerTest(config, port)); +std::unique_ptr CreateAsyncServer(const ServerConfig &config, + int port) { + return std::unique_ptr(new AsyncQpsServerTest(config, port)); } - }// namespace testing -}// namespace grpc +} // namespace testing +} // namespace grpc diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc index e598fb51ae0..88a201fe790 100644 --- a/test/cpp/qps/server_sync.cc +++ b/test/cpp/qps/server_sync.cc @@ -62,8 +62,9 @@ class TestServiceImpl GRPC_FINAL : public TestService::Service { Status UnaryCall(ServerContext* context, const SimpleRequest* request, SimpleResponse* response) override { if (request->has_response_size() && request->response_size() > 0) { - if (!Server::SetPayload(request->response_type(), request->response_size(), - response->mutable_payload())) { + if (!Server::SetPayload(request->response_type(), + request->response_size(), + response->mutable_payload())) { return Status(grpc::StatusCode::INTERNAL, "Error creating payload."); } } @@ -74,8 +75,7 @@ class TestServiceImpl GRPC_FINAL : public TestService::Service { class SynchronousServer GRPC_FINAL : public grpc::testing::Server { public: SynchronousServer(const ServerConfig& config, int port) - : thread_pool_(config.threads()), - impl_(MakeImpl(port)) {} + : thread_pool_(config.threads()), impl_(MakeImpl(port)) {} private: std::unique_ptr MakeImpl(int port) { diff --git a/test/cpp/qps/stats.h b/test/cpp/qps/stats.h index f7a4f8c05de..ca59390ad79 100644 --- a/test/cpp/qps/stats.h +++ b/test/cpp/qps/stats.h @@ -44,7 +44,7 @@ template double sum(const T& container, F functor) { double r = 0; for (auto v : container) { - r += functor(v); + r += functor(v); } return r; } @@ -54,7 +54,7 @@ double average(const T& container, F functor) { return sum(container, functor) / container.size(); } -} // namespace testing -} // namespace grpc +} // namespace testing +} // namespace grpc #endif From 2eaf1596bb4f724dc4331c6e1de9c91b56577fa2 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 14:47:18 -0800 Subject: [PATCH 25/27] ACTUALLY set the server thread pool --- test/cpp/qps/server_sync.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc index 88a201fe790..8a75b73af3d 100644 --- a/test/cpp/qps/server_sync.cc +++ b/test/cpp/qps/server_sync.cc @@ -88,6 +88,8 @@ class SynchronousServer GRPC_FINAL : public grpc::testing::Server { builder.RegisterService(&service_); + builder.SetThreadPool(&thread_pool_); + return builder.BuildAndStart(); } From 78524b75d7d449298e52c6dc546021fbb33d61cb Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 17:13:03 -0800 Subject: [PATCH 26/27] Compile fix --- test/cpp/qps/worker.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc index 45b8b6dd9a9..3a46a22665d 100644 --- a/test/cpp/qps/worker.cc +++ b/test/cpp/qps/worker.cc @@ -93,7 +93,7 @@ std::unique_ptr CreateServer(const ServerConfig& config) { abort(); } -class WorkerImpl final : public Worker::Service { +class WorkerImpl GRPC_FINAL : public Worker::Service { public: WorkerImpl() : acquired_(false) {} From 43ef582e42b2e5d3b5052523d9dee1fb2ee0ae33 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Mar 2015 20:01:09 -0800 Subject: [PATCH 27/27] override --> GRPC_OVERRIDE --- test/cpp/qps/server_sync.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc index 8a75b73af3d..beee688608e 100644 --- a/test/cpp/qps/server_sync.cc +++ b/test/cpp/qps/server_sync.cc @@ -60,7 +60,7 @@ namespace testing { class TestServiceImpl GRPC_FINAL : public TestService::Service { public: Status UnaryCall(ServerContext* context, const SimpleRequest* request, - SimpleResponse* response) override { + SimpleResponse* response) GRPC_OVERRIDE { if (request->has_response_size() && request->response_size() > 0) { if (!Server::SetPayload(request->response_type(), request->response_size(),