1 //
2 //
3 // Copyright 2024 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 // Benchmark gRPC end2end in various configurations for chaotic good
20 // TODO(ctiller): fold back into bm_fullstack_unary_ping_pong.cc once chaotic
21 // good can run without custom experiment configuration.
22 
23 #include "src/cpp/ext/chaotic_good.h"
24 #include "test/core/util/test_config.h"
25 #include "test/cpp/microbenchmarks/fullstack_unary_ping_pong.h"
26 #include "test/cpp/util/test_config.h"
27 
28 namespace grpc {
29 namespace testing {
30 
31 class ChaoticGoodFixture : public BaseFixture {
32  public:
ChaoticGoodFixture(Service * service,const FixtureConfiguration & config=FixtureConfiguration ())33   explicit ChaoticGoodFixture(
34       Service* service,
35       const FixtureConfiguration& config = FixtureConfiguration()) {
36     auto address = MakeAddress(&port_);
37     ServerBuilder b;
38     if (address.length() > 0) {
39       b.AddListeningPort(address, ChaoticGoodInsecureServerCredentials());
40     }
41     cq_ = b.AddCompletionQueue(true);
42     b.RegisterService(service);
43     config.ApplyCommonServerBuilderConfig(&b);
44     server_ = b.BuildAndStart();
45     ChannelArguments args;
46     config.ApplyCommonChannelArguments(&args);
47     if (address.length() > 0) {
48       channel_ = grpc::CreateCustomChannel(
49           address, ChaoticGoodInsecureChannelCredentials(), args);
50     } else {
51       channel_ = server_->InProcessChannel(args);
52     }
53   }
54 
~ChaoticGoodFixture()55   ~ChaoticGoodFixture() override {
56     server_->Shutdown(grpc_timeout_milliseconds_to_deadline(0));
57     cq_->Shutdown();
58     void* tag;
59     bool ok;
60     while (cq_->Next(&tag, &ok)) {
61     }
62     grpc_recycle_unused_port(port_);
63   }
64 
cq()65   ServerCompletionQueue* cq() { return cq_.get(); }
channel()66   std::shared_ptr<Channel> channel() { return channel_; }
67 
68  private:
MakeAddress(int * port)69   static std::string MakeAddress(int* port) {
70     *port = grpc_pick_unused_port_or_die();
71     std::stringstream addr;
72     addr << "localhost:" << *port;
73     return addr.str();
74   }
75 
76   std::unique_ptr<Server> server_;
77   std::unique_ptr<ServerCompletionQueue> cq_;
78   std::shared_ptr<Channel> channel_;
79   int port_;
80 };
81 
82 //******************************************************************************
83 // CONFIGURATIONS
84 //
85 
86 // Replace "benchmark::internal::Benchmark" with "::testing::Benchmark" to use
87 // internal microbenchmarking tooling
SweepSizesArgs(benchmark::internal::Benchmark * b)88 static void SweepSizesArgs(benchmark::internal::Benchmark* b) {
89   b->Args({0, 0});
90   for (int i = 1; i <= 128 * 1024 * 1024; i *= 8) {
91     b->Args({i, 0});
92     b->Args({0, i});
93     b->Args({i, i});
94   }
95 }
96 
97 BENCHMARK_TEMPLATE(BM_UnaryPingPong, ChaoticGoodFixture, NoOpMutator,
98                    NoOpMutator)
99     ->Apply(SweepSizesArgs);
100 
101 }  // namespace testing
102 }  // namespace grpc
103 
104 // Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
105 // and others do not. This allows us to support both modes.
106 namespace benchmark {
RunTheBenchmarksNamespaced()107 void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
108 }  // namespace benchmark
109 
main(int argc,char ** argv)110 int main(int argc, char** argv) {
111   grpc_core::ForceEnableExperiment("event_engine_client", true);
112   grpc_core::ForceEnableExperiment("event_engine_listener", true);
113   grpc_core::ForceEnableExperiment("promise_based_client_call", true);
114   grpc_core::ForceEnableExperiment("promise_based_server_call", true);
115   grpc_core::ForceEnableExperiment("chaotic_good", true);
116   grpc::testing::TestEnvironment env(&argc, argv);
117   LibraryInitializer libInit;
118   ::benchmark::Initialize(&argc, argv);
119   grpc::testing::InitTest(&argc, &argv, false);
120   benchmark::RunTheBenchmarksNamespaced();
121   return 0;
122 }
123