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