Merge pull request #18881 from nanahpang/master
Add microbenchmark for callback apispull/18897/head
commit
f2efc92cc8
14 changed files with 1314 additions and 17 deletions
@ -0,0 +1,136 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2019 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include "test/cpp/microbenchmarks/callback_streaming_ping_pong.h" |
||||
#include "test/cpp/util/test_config.h" |
||||
|
||||
namespace grpc { |
||||
namespace testing { |
||||
|
||||
/*******************************************************************************
|
||||
* CONFIGURATIONS |
||||
*/ |
||||
|
||||
// Replace "benchmark::internal::Benchmark" with "::testing::Benchmark" to use
|
||||
// internal microbenchmarking tooling
|
||||
static void StreamingPingPongMsgSizeArgs(benchmark::internal::Benchmark* b) { |
||||
// base case: 0 byte ping-pong msgs
|
||||
b->Args({0, 1}); |
||||
b->Args({0, 2}); |
||||
|
||||
for (int msg_size = 1; msg_size <= 128 * 1024 * 1024; msg_size *= 8) { |
||||
b->Args({msg_size, 1}); |
||||
b->Args({msg_size, 2}); |
||||
} |
||||
} |
||||
|
||||
// Replace "benchmark::internal::Benchmark" with "::testing::Benchmark" to use
|
||||
// internal microbenchmarking tooling
|
||||
static void StreamingPingPongMsgsNumberArgs(benchmark::internal::Benchmark* b) { |
||||
for (int msg_number = 1; msg_number <= 256 * 1024; msg_number *= 8) { |
||||
b->Args({0, msg_number}); |
||||
b->Args({1024, msg_number}); |
||||
} |
||||
} |
||||
|
||||
// Streaming with different message size
|
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, NoOpMutator, |
||||
NoOpMutator) |
||||
->Apply(StreamingPingPongMsgSizeArgs); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, MinInProcess, NoOpMutator, |
||||
NoOpMutator) |
||||
->Apply(StreamingPingPongMsgSizeArgs); |
||||
|
||||
// Streaming with different message number
|
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, NoOpMutator, |
||||
NoOpMutator) |
||||
->Apply(StreamingPingPongMsgsNumberArgs); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, MinInProcess, NoOpMutator, |
||||
NoOpMutator) |
||||
->Apply(StreamingPingPongMsgsNumberArgs); |
||||
|
||||
// Client context with different metadata
|
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<10>, 1>, NoOpMutator) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<31>, 1>, NoOpMutator) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<100>, 1>, |
||||
NoOpMutator) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<10>, 2>, NoOpMutator) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<31>, 2>, NoOpMutator) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<100>, 2>, |
||||
NoOpMutator) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, |
||||
Client_AddMetadata<RandomAsciiMetadata<10>, 1>, NoOpMutator) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, |
||||
Client_AddMetadata<RandomAsciiMetadata<31>, 1>, NoOpMutator) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, |
||||
Client_AddMetadata<RandomAsciiMetadata<100>, 1>, NoOpMutator) |
||||
->Args({0, 1}); |
||||
|
||||
// Server context with different metadata
|
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomBinaryMetadata<10>, 1>) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomBinaryMetadata<31>, 1>) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomBinaryMetadata<100>, 1>) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomAsciiMetadata<10>, 1>) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomAsciiMetadata<31>, 1>) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomAsciiMetadata<100>, 1>) |
||||
->Args({0, 1}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackBidiStreaming, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomAsciiMetadata<10>, 100>) |
||||
->Args({0, 1}); |
||||
|
||||
} // namespace testing
|
||||
} // namespace grpc
|
||||
|
||||
// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
|
||||
// and others do not. This allows us to support both modes.
|
||||
namespace benchmark { |
||||
void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); } |
||||
} // namespace benchmark
|
||||
|
||||
int main(int argc, char** argv) { |
||||
LibraryInitializer libInit; |
||||
::benchmark::Initialize(&argc, argv); |
||||
::grpc::testing::InitTest(&argc, &argv, false); |
||||
benchmark::RunTheBenchmarksNamespaced(); |
||||
return 0; |
||||
} |
@ -0,0 +1,118 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2019 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include "test/cpp/microbenchmarks/callback_unary_ping_pong.h" |
||||
#include "test/cpp/util/test_config.h" |
||||
|
||||
namespace grpc { |
||||
namespace testing { |
||||
|
||||
/*******************************************************************************
|
||||
* CONFIGURATIONS |
||||
*/ |
||||
|
||||
// Replace "benchmark::internal::Benchmark" with "::testing::Benchmark" to use
|
||||
// internal microbenchmarking tooling
|
||||
static void SweepSizesArgs(benchmark::internal::Benchmark* b) { |
||||
b->Args({0, 0}); |
||||
for (int i = 1; i <= 128 * 1024 * 1024; i *= 8) { |
||||
// First argument is the message size of request
|
||||
// Second argument is the message size of response
|
||||
b->Args({i, 0}); |
||||
b->Args({0, i}); |
||||
b->Args({i, i}); |
||||
} |
||||
} |
||||
|
||||
// Unary ping pong with different message size of request and response
|
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, NoOpMutator, |
||||
NoOpMutator) |
||||
->Apply(SweepSizesArgs); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, MinInProcess, NoOpMutator, |
||||
NoOpMutator) |
||||
->Apply(SweepSizesArgs); |
||||
|
||||
// Client context with different metadata
|
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<10>, 1>, NoOpMutator) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<31>, 1>, NoOpMutator) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<100>, 1>, |
||||
NoOpMutator) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<10>, 2>, NoOpMutator) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<31>, 2>, NoOpMutator) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, |
||||
Client_AddMetadata<RandomBinaryMetadata<100>, 2>, |
||||
NoOpMutator) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, |
||||
Client_AddMetadata<RandomAsciiMetadata<10>, 1>, NoOpMutator) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, |
||||
Client_AddMetadata<RandomAsciiMetadata<31>, 1>, NoOpMutator) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, |
||||
Client_AddMetadata<RandomAsciiMetadata<100>, 1>, NoOpMutator) |
||||
->Args({0, 0}); |
||||
|
||||
// Server context with different metadata
|
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomBinaryMetadata<10>, 1>) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomBinaryMetadata<31>, 1>) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomBinaryMetadata<100>, 1>) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomAsciiMetadata<10>, 1>) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomAsciiMetadata<31>, 1>) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomAsciiMetadata<100>, 1>) |
||||
->Args({0, 0}); |
||||
BENCHMARK_TEMPLATE(BM_CallbackUnaryPingPong, InProcess, NoOpMutator, |
||||
Server_AddInitialMetadata<RandomAsciiMetadata<10>, 100>) |
||||
->Args({0, 0}); |
||||
} // namespace testing
|
||||
} // namespace grpc
|
||||
|
||||
// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
|
||||
// and others do not. This allows us to support both modes.
|
||||
namespace benchmark { |
||||
void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); } |
||||
} // namespace benchmark
|
||||
|
||||
int main(int argc, char** argv) { |
||||
LibraryInitializer libInit; |
||||
::benchmark::Initialize(&argc, argv); |
||||
::grpc::testing::InitTest(&argc, &argv, false); |
||||
benchmark::RunTheBenchmarksNamespaced(); |
||||
return 0; |
||||
} |
@ -0,0 +1,150 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2019 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef TEST_CPP_MICROBENCHMARKS_CALLBACK_STREAMING_PING_PONG_H |
||||
#define TEST_CPP_MICROBENCHMARKS_CALLBACK_STREAMING_PING_PONG_H |
||||
|
||||
#include <benchmark/benchmark.h> |
||||
#include <sstream> |
||||
#include "src/core/lib/profiling/timers.h" |
||||
#include "src/proto/grpc/testing/echo.grpc.pb.h" |
||||
#include "test/cpp/microbenchmarks/callback_test_service.h" |
||||
#include "test/cpp/microbenchmarks/fullstack_context_mutators.h" |
||||
#include "test/cpp/microbenchmarks/fullstack_fixtures.h" |
||||
|
||||
namespace grpc { |
||||
namespace testing { |
||||
|
||||
/*******************************************************************************
|
||||
* BENCHMARKING KERNELS |
||||
*/ |
||||
|
||||
class BidiClient |
||||
: public grpc::experimental::ClientBidiReactor<EchoRequest, EchoResponse> { |
||||
public: |
||||
BidiClient(benchmark::State* state, EchoTestService::Stub* stub, |
||||
ClientContext* cli_ctx, EchoRequest* request, |
||||
EchoResponse* response) |
||||
: state_{state}, |
||||
stub_{stub}, |
||||
cli_ctx_{cli_ctx}, |
||||
request_{request}, |
||||
response_{response} { |
||||
msgs_size_ = state->range(0); |
||||
msgs_to_send_ = state->range(1); |
||||
StartNewRpc(); |
||||
} |
||||
|
||||
void OnReadDone(bool ok) override { |
||||
if (!ok) { |
||||
gpr_log(GPR_ERROR, "Client read failed"); |
||||
return; |
||||
} |
||||
MaybeWrite(); |
||||
} |
||||
|
||||
void OnWriteDone(bool ok) override { |
||||
if (!ok) { |
||||
gpr_log(GPR_ERROR, "Client write failed"); |
||||
return; |
||||
} |
||||
writes_complete_++; |
||||
StartRead(response_); |
||||
} |
||||
|
||||
void OnDone(const Status& s) override { |
||||
GPR_ASSERT(s.ok()); |
||||
GPR_ASSERT(writes_complete_ == msgs_to_send_); |
||||
if (state_->KeepRunning()) { |
||||
writes_complete_ = 0; |
||||
StartNewRpc(); |
||||
} else { |
||||
std::unique_lock<std::mutex> l(mu); |
||||
done = true; |
||||
cv.notify_one(); |
||||
} |
||||
} |
||||
|
||||
void StartNewRpc() { |
||||
cli_ctx_->~ClientContext(); |
||||
new (cli_ctx_) ClientContext(); |
||||
cli_ctx_->AddMetadata(kServerMessageSize, grpc::to_string(msgs_size_)); |
||||
stub_->experimental_async()->BidiStream(cli_ctx_, this); |
||||
MaybeWrite(); |
||||
StartCall(); |
||||
} |
||||
|
||||
void Await() { |
||||
std::unique_lock<std::mutex> l(mu); |
||||
while (!done) { |
||||
cv.wait(l); |
||||
} |
||||
} |
||||
|
||||
private: |
||||
void MaybeWrite() { |
||||
if (writes_complete_ < msgs_to_send_) { |
||||
StartWrite(request_); |
||||
} else { |
||||
StartWritesDone(); |
||||
} |
||||
} |
||||
|
||||
benchmark::State* state_; |
||||
EchoTestService::Stub* stub_; |
||||
ClientContext* cli_ctx_; |
||||
EchoRequest* request_; |
||||
EchoResponse* response_; |
||||
int writes_complete_{0}; |
||||
int msgs_to_send_; |
||||
int msgs_size_; |
||||
std::mutex mu; |
||||
std::condition_variable cv; |
||||
bool done; |
||||
}; |
||||
|
||||
template <class Fixture, class ClientContextMutator, class ServerContextMutator> |
||||
static void BM_CallbackBidiStreaming(benchmark::State& state) { |
||||
int message_size = state.range(0); |
||||
int max_ping_pongs = state.range(1); |
||||
CallbackStreamingTestService service; |
||||
std::unique_ptr<Fixture> fixture(new Fixture(&service)); |
||||
std::unique_ptr<EchoTestService::Stub> stub_( |
||||
EchoTestService::NewStub(fixture->channel())); |
||||
EchoRequest request; |
||||
EchoResponse response; |
||||
ClientContext cli_ctx; |
||||
if (message_size > 0) { |
||||
request.set_message(std::string(message_size, 'a')); |
||||
} else { |
||||
request.set_message(""); |
||||
} |
||||
if (state.KeepRunning()) { |
||||
GPR_TIMER_SCOPE("BenchmarkCycle", 0); |
||||
BidiClient test{&state, stub_.get(), &cli_ctx, &request, &response}; |
||||
test.Await(); |
||||
} |
||||
fixture->Finish(state); |
||||
fixture.reset(); |
||||
state.SetBytesProcessed(2 * message_size * max_ping_pongs * |
||||
state.iterations()); |
||||
} |
||||
|
||||
} // namespace testing
|
||||
} // namespace grpc
|
||||
#endif // TEST_CPP_MICROBENCHMARKS_CALLBACK_STREAMING_PING_PONG_H
|
@ -0,0 +1,112 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2019 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include "test/cpp/microbenchmarks/callback_test_service.h" |
||||
|
||||
namespace grpc { |
||||
namespace testing { |
||||
namespace { |
||||
|
||||
grpc::string ToString(const grpc::string_ref& r) { |
||||
return grpc::string(r.data(), r.size()); |
||||
} |
||||
|
||||
int GetIntValueFromMetadataHelper( |
||||
const char* key, |
||||
const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, |
||||
int default_value) { |
||||
if (metadata.find(key) != metadata.end()) { |
||||
std::istringstream iss(ToString(metadata.find(key)->second)); |
||||
iss >> default_value; |
||||
} |
||||
|
||||
return default_value; |
||||
} |
||||
|
||||
int GetIntValueFromMetadata( |
||||
const char* key, |
||||
const std::multimap<grpc::string_ref, grpc::string_ref>& metadata, |
||||
int default_value) { |
||||
return GetIntValueFromMetadataHelper(key, metadata, default_value); |
||||
} |
||||
} // namespace
|
||||
|
||||
void CallbackStreamingTestService::Echo( |
||||
ServerContext* context, const EchoRequest* request, EchoResponse* response, |
||||
experimental::ServerCallbackRpcController* controller) { |
||||
int response_msgs_size = GetIntValueFromMetadata( |
||||
kServerMessageSize, context->client_metadata(), 0); |
||||
if (response_msgs_size > 0) { |
||||
response->set_message(std::string(response_msgs_size, 'a')); |
||||
} else { |
||||
response->set_message(""); |
||||
} |
||||
controller->Finish(Status::OK); |
||||
} |
||||
|
||||
experimental::ServerBidiReactor<EchoRequest, EchoResponse>* |
||||
CallbackStreamingTestService::BidiStream() { |
||||
class Reactor |
||||
: public experimental::ServerBidiReactor<EchoRequest, EchoResponse> { |
||||
public: |
||||
Reactor() {} |
||||
void OnStarted(ServerContext* context) override { |
||||
ctx_ = context; |
||||
message_size_ = GetIntValueFromMetadata(kServerMessageSize, |
||||
context->client_metadata(), 0); |
||||
StartRead(&request_); |
||||
} |
||||
void OnDone() override { |
||||
GPR_ASSERT(finished_); |
||||
delete this; |
||||
} |
||||
void OnCancel() override {} |
||||
void OnReadDone(bool ok) override { |
||||
if (!ok) { |
||||
// Stream is over
|
||||
Finish(::grpc::Status::OK); |
||||
finished_ = true; |
||||
return; |
||||
} |
||||
if (message_size_ > 0) { |
||||
response_.set_message(std::string(message_size_, 'a')); |
||||
} else { |
||||
response_.set_message(""); |
||||
} |
||||
StartWrite(&response_); |
||||
} |
||||
void OnWriteDone(bool ok) override { |
||||
if (!ok) { |
||||
gpr_log(GPR_ERROR, "Server write failed"); |
||||
return; |
||||
} |
||||
StartRead(&request_); |
||||
} |
||||
|
||||
private: |
||||
ServerContext* ctx_; |
||||
EchoRequest request_; |
||||
EchoResponse response_; |
||||
int message_size_; |
||||
bool finished_{false}; |
||||
}; |
||||
|
||||
return new Reactor; |
||||
} |
||||
} // namespace testing
|
||||
} // namespace grpc
|
@ -0,0 +1,48 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2019 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef TEST_CPP_MICROBENCHMARKS_CALLBACK_TEST_SERVICE_H |
||||
#define TEST_CPP_MICROBENCHMARKS_CALLBACK_TEST_SERVICE_H |
||||
|
||||
#include <benchmark/benchmark.h> |
||||
#include <condition_variable> |
||||
#include <memory> |
||||
#include <mutex> |
||||
#include <sstream> |
||||
#include "src/proto/grpc/testing/echo.grpc.pb.h" |
||||
#include "test/cpp/util/string_ref_helper.h" |
||||
|
||||
namespace grpc { |
||||
namespace testing { |
||||
|
||||
const char* const kServerMessageSize = "server_message_size"; |
||||
|
||||
class CallbackStreamingTestService |
||||
: public EchoTestService::ExperimentalCallbackService { |
||||
public: |
||||
CallbackStreamingTestService() {} |
||||
void Echo(ServerContext* context, const EchoRequest* request, |
||||
EchoResponse* response, |
||||
experimental::ServerCallbackRpcController* controller) override; |
||||
|
||||
experimental::ServerBidiReactor<EchoRequest, EchoResponse>* BidiStream() |
||||
override; |
||||
}; |
||||
} // namespace testing
|
||||
} // namespace grpc
|
||||
#endif // TEST_CPP_MICROBENCHMARKS_CALLBACK_TEST_SERVICE_H
|
@ -0,0 +1,101 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2019 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
/* Benchmark gRPC end2end in various configurations */ |
||||
|
||||
#ifndef TEST_CPP_MICROBENCHMARKS_CALLBACK_UNARY_PING_PONG_H |
||||
#define TEST_CPP_MICROBENCHMARKS_CALLBACK_UNARY_PING_PONG_H |
||||
|
||||
#include <benchmark/benchmark.h> |
||||
#include <sstream> |
||||
#include "src/core/lib/profiling/timers.h" |
||||
#include "src/proto/grpc/testing/echo.grpc.pb.h" |
||||
#include "test/cpp/microbenchmarks/callback_test_service.h" |
||||
#include "test/cpp/microbenchmarks/fullstack_context_mutators.h" |
||||
#include "test/cpp/microbenchmarks/fullstack_fixtures.h" |
||||
|
||||
namespace grpc { |
||||
namespace testing { |
||||
|
||||
/*******************************************************************************
|
||||
* BENCHMARKING KERNELS |
||||
*/ |
||||
|
||||
void SendCallbackUnaryPingPong(benchmark::State* state, ClientContext* cli_ctx, |
||||
EchoRequest* request, EchoResponse* response, |
||||
EchoTestService::Stub* stub_, bool* done, |
||||
std::mutex* mu, std::condition_variable* cv) { |
||||
int response_msgs_size = state->range(1); |
||||
cli_ctx->AddMetadata(kServerMessageSize, grpc::to_string(response_msgs_size)); |
||||
stub_->experimental_async()->Echo( |
||||
cli_ctx, request, response, |
||||
[state, cli_ctx, request, response, stub_, done, mu, cv](Status s) { |
||||
GPR_ASSERT(s.ok()); |
||||
if (state->KeepRunning()) { |
||||
cli_ctx->~ClientContext(); |
||||
new (cli_ctx) ClientContext(); |
||||
SendCallbackUnaryPingPong(state, cli_ctx, request, response, stub_, |
||||
done, mu, cv); |
||||
} else { |
||||
std::lock_guard<std::mutex> l(*mu); |
||||
*done = true; |
||||
cv->notify_one(); |
||||
} |
||||
}); |
||||
}; |
||||
|
||||
template <class Fixture, class ClientContextMutator, class ServerContextMutator> |
||||
static void BM_CallbackUnaryPingPong(benchmark::State& state) { |
||||
int request_msgs_size = state.range(0); |
||||
int response_msgs_size = state.range(1); |
||||
CallbackStreamingTestService service; |
||||
std::unique_ptr<Fixture> fixture(new Fixture(&service)); |
||||
std::unique_ptr<EchoTestService::Stub> stub_( |
||||
EchoTestService::NewStub(fixture->channel())); |
||||
EchoRequest request; |
||||
EchoResponse response; |
||||
ClientContext cli_ctx; |
||||
|
||||
if (request_msgs_size > 0) { |
||||
request.set_message(std::string(request_msgs_size, 'a')); |
||||
} else { |
||||
request.set_message(""); |
||||
} |
||||
|
||||
std::mutex mu; |
||||
std::condition_variable cv; |
||||
bool done = false; |
||||
if (state.KeepRunning()) { |
||||
GPR_TIMER_SCOPE("BenchmarkCycle", 0); |
||||
SendCallbackUnaryPingPong(&state, &cli_ctx, &request, &response, |
||||
stub_.get(), &done, &mu, &cv); |
||||
} |
||||
std::unique_lock<std::mutex> l(mu); |
||||
while (!done) { |
||||
cv.wait(l); |
||||
} |
||||
fixture->Finish(state); |
||||
fixture.reset(); |
||||
state.SetBytesProcessed(request_msgs_size * state.iterations() + |
||||
response_msgs_size * state.iterations()); |
||||
} |
||||
|
||||
} // namespace testing
|
||||
} // namespace grpc
|
||||
|
||||
#endif // TEST_CPP_MICROBENCHMARKS_FULLSTACK_UNARY_PING_PONG_H
|
Loading…
Reference in new issue