• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 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 /* Test various operations on grpc_error */
20 
21 #include <benchmark/benchmark.h>
22 #include <memory>
23 
24 #include "src/core/lib/iomgr/error.h"
25 #include "src/core/lib/transport/error_utils.h"
26 
27 #include "test/core/util/test_config.h"
28 #include "test/cpp/microbenchmarks/helpers.h"
29 #include "test/cpp/util/test_config.h"
30 
31 class ErrorDeleter {
32  public:
operator ()(grpc_error * error)33   void operator()(grpc_error* error) { GRPC_ERROR_UNREF(error); }
34 };
35 typedef std::unique_ptr<grpc_error, ErrorDeleter> ErrorPtr;
36 
BM_ErrorCreateFromStatic(benchmark::State & state)37 static void BM_ErrorCreateFromStatic(benchmark::State& state) {
38   TrackCounters track_counters;
39   for (auto _ : state) {
40     GRPC_ERROR_UNREF(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"));
41   }
42   track_counters.Finish(state);
43 }
44 BENCHMARK(BM_ErrorCreateFromStatic);
45 
BM_ErrorCreateFromCopied(benchmark::State & state)46 static void BM_ErrorCreateFromCopied(benchmark::State& state) {
47   TrackCounters track_counters;
48   for (auto _ : state) {
49     GRPC_ERROR_UNREF(GRPC_ERROR_CREATE_FROM_COPIED_STRING("Error not inline"));
50   }
51   track_counters.Finish(state);
52 }
53 BENCHMARK(BM_ErrorCreateFromCopied);
54 
BM_ErrorCreateAndSetStatus(benchmark::State & state)55 static void BM_ErrorCreateAndSetStatus(benchmark::State& state) {
56   TrackCounters track_counters;
57   for (auto _ : state) {
58     GRPC_ERROR_UNREF(
59         grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"),
60                            GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_ABORTED));
61   }
62   track_counters.Finish(state);
63 }
64 BENCHMARK(BM_ErrorCreateAndSetStatus);
65 
BM_ErrorCreateAndSetIntAndStr(benchmark::State & state)66 static void BM_ErrorCreateAndSetIntAndStr(benchmark::State& state) {
67   TrackCounters track_counters;
68   for (auto _ : state) {
69     GRPC_ERROR_UNREF(grpc_error_set_str(
70         grpc_error_set_int(
71             GRPC_ERROR_CREATE_FROM_STATIC_STRING("GOAWAY received"),
72             GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)0),
73         GRPC_ERROR_STR_RAW_BYTES, grpc_slice_from_static_string("raw bytes")));
74   }
75   track_counters.Finish(state);
76 }
77 BENCHMARK(BM_ErrorCreateAndSetIntAndStr);
78 
BM_ErrorCreateAndSetIntLoop(benchmark::State & state)79 static void BM_ErrorCreateAndSetIntLoop(benchmark::State& state) {
80   TrackCounters track_counters;
81   grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error");
82   int n = 0;
83   for (auto _ : state) {
84     error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, n++);
85   }
86   GRPC_ERROR_UNREF(error);
87   track_counters.Finish(state);
88 }
89 BENCHMARK(BM_ErrorCreateAndSetIntLoop);
90 
BM_ErrorCreateAndSetStrLoop(benchmark::State & state)91 static void BM_ErrorCreateAndSetStrLoop(benchmark::State& state) {
92   TrackCounters track_counters;
93   grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error");
94   const char* str = "hello";
95   for (auto _ : state) {
96     error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
97                                grpc_slice_from_static_string(str));
98   }
99   GRPC_ERROR_UNREF(error);
100   track_counters.Finish(state);
101 }
102 BENCHMARK(BM_ErrorCreateAndSetStrLoop);
103 
BM_ErrorRefUnref(benchmark::State & state)104 static void BM_ErrorRefUnref(benchmark::State& state) {
105   TrackCounters track_counters;
106   grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error");
107   for (auto _ : state) {
108     GRPC_ERROR_UNREF(GRPC_ERROR_REF(error));
109   }
110   GRPC_ERROR_UNREF(error);
111   track_counters.Finish(state);
112 }
113 BENCHMARK(BM_ErrorRefUnref);
114 
BM_ErrorUnrefNone(benchmark::State & state)115 static void BM_ErrorUnrefNone(benchmark::State& state) {
116   TrackCounters track_counters;
117   for (auto _ : state) {
118     GRPC_ERROR_UNREF(GRPC_ERROR_NONE);
119   }
120 }
121 BENCHMARK(BM_ErrorUnrefNone);
122 
BM_ErrorGetIntFromNoError(benchmark::State & state)123 static void BM_ErrorGetIntFromNoError(benchmark::State& state) {
124   TrackCounters track_counters;
125   for (auto _ : state) {
126     intptr_t value;
127     grpc_error_get_int(GRPC_ERROR_NONE, GRPC_ERROR_INT_GRPC_STATUS, &value);
128   }
129   track_counters.Finish(state);
130 }
131 BENCHMARK(BM_ErrorGetIntFromNoError);
132 
BM_ErrorGetMissingInt(benchmark::State & state)133 static void BM_ErrorGetMissingInt(benchmark::State& state) {
134   TrackCounters track_counters;
135   ErrorPtr error(grpc_error_set_int(
136       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_INDEX, 1));
137   for (auto _ : state) {
138     intptr_t value;
139     grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
140   }
141   track_counters.Finish(state);
142 }
143 BENCHMARK(BM_ErrorGetMissingInt);
144 
BM_ErrorGetPresentInt(benchmark::State & state)145 static void BM_ErrorGetPresentInt(benchmark::State& state) {
146   TrackCounters track_counters;
147   ErrorPtr error(grpc_error_set_int(
148       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_OFFSET, 1));
149   for (auto _ : state) {
150     intptr_t value;
151     grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
152   }
153   track_counters.Finish(state);
154 }
155 BENCHMARK(BM_ErrorGetPresentInt);
156 
157 // Fixtures for tests: generate different kinds of errors
158 class ErrorNone {
159  public:
deadline() const160   grpc_millis deadline() const { return deadline_; }
error() const161   grpc_error* error() const { return GRPC_ERROR_NONE; }
162 
163  private:
164   const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
165 };
166 
167 class ErrorCancelled {
168  public:
deadline() const169   grpc_millis deadline() const { return deadline_; }
error() const170   grpc_error* error() const { return GRPC_ERROR_CANCELLED; }
171 
172  private:
173   const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
174 };
175 
176 class SimpleError {
177  public:
deadline() const178   grpc_millis deadline() const { return deadline_; }
error() const179   grpc_error* error() const { return error_.get(); }
180 
181  private:
182   const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
183   ErrorPtr error_{GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error")};
184 };
185 
186 class ErrorWithGrpcStatus {
187  public:
deadline() const188   grpc_millis deadline() const { return deadline_; }
error() const189   grpc_error* error() const { return error_.get(); }
190 
191  private:
192   const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
193   ErrorPtr error_{grpc_error_set_int(
194       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_GRPC_STATUS,
195       GRPC_STATUS_UNIMPLEMENTED)};
196 };
197 
198 class ErrorWithHttpError {
199  public:
deadline() const200   grpc_millis deadline() const { return deadline_; }
error() const201   grpc_error* error() const { return error_.get(); }
202 
203  private:
204   const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
205   ErrorPtr error_{grpc_error_set_int(
206       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_HTTP2_ERROR,
207       GRPC_HTTP2_COMPRESSION_ERROR)};
208 };
209 
210 class ErrorWithNestedGrpcStatus {
211  public:
deadline() const212   grpc_millis deadline() const { return deadline_; }
error() const213   grpc_error* error() const { return error_.get(); }
214 
215  private:
216   const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
217   ErrorPtr nested_error_{grpc_error_set_int(
218       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_GRPC_STATUS,
219       GRPC_STATUS_UNIMPLEMENTED)};
220   grpc_error* nested_errors_[1] = {nested_error_.get()};
221   ErrorPtr error_{GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
222       "Error", nested_errors_, 1)};
223 };
224 
225 template <class Fixture>
BM_ErrorStringOnNewError(benchmark::State & state)226 static void BM_ErrorStringOnNewError(benchmark::State& state) {
227   TrackCounters track_counters;
228   for (auto _ : state) {
229     Fixture fixture;
230     grpc_error_string(fixture.error());
231   }
232   track_counters.Finish(state);
233 }
234 
235 template <class Fixture>
BM_ErrorStringRepeatedly(benchmark::State & state)236 static void BM_ErrorStringRepeatedly(benchmark::State& state) {
237   TrackCounters track_counters;
238   Fixture fixture;
239   for (auto _ : state) {
240     grpc_error_string(fixture.error());
241   }
242   track_counters.Finish(state);
243 }
244 
245 template <class Fixture>
BM_ErrorGetStatus(benchmark::State & state)246 static void BM_ErrorGetStatus(benchmark::State& state) {
247   TrackCounters track_counters;
248   Fixture fixture;
249   grpc_core::ExecCtx exec_ctx;
250   for (auto _ : state) {
251     grpc_status_code status;
252     grpc_slice slice;
253     grpc_error_get_status(fixture.error(), fixture.deadline(), &status, &slice,
254                           nullptr, nullptr);
255   }
256 
257   track_counters.Finish(state);
258 }
259 
260 template <class Fixture>
BM_ErrorGetStatusCode(benchmark::State & state)261 static void BM_ErrorGetStatusCode(benchmark::State& state) {
262   TrackCounters track_counters;
263   Fixture fixture;
264   grpc_core::ExecCtx exec_ctx;
265   for (auto _ : state) {
266     grpc_status_code status;
267     grpc_error_get_status(fixture.error(), fixture.deadline(), &status, nullptr,
268                           nullptr, nullptr);
269   }
270 
271   track_counters.Finish(state);
272 }
273 
274 template <class Fixture>
BM_ErrorHttpError(benchmark::State & state)275 static void BM_ErrorHttpError(benchmark::State& state) {
276   TrackCounters track_counters;
277   Fixture fixture;
278   grpc_core::ExecCtx exec_ctx;
279   for (auto _ : state) {
280     grpc_http2_error_code error;
281     grpc_error_get_status(fixture.error(), fixture.deadline(), nullptr, nullptr,
282                           &error, nullptr);
283   }
284 
285   track_counters.Finish(state);
286 }
287 
288 template <class Fixture>
BM_HasClearGrpcStatus(benchmark::State & state)289 static void BM_HasClearGrpcStatus(benchmark::State& state) {
290   TrackCounters track_counters;
291   Fixture fixture;
292   for (auto _ : state) {
293     grpc_error_has_clear_grpc_status(fixture.error());
294   }
295   track_counters.Finish(state);
296 }
297 
298 #define BENCHMARK_SUITE(fixture)                         \
299   BENCHMARK_TEMPLATE(BM_ErrorStringOnNewError, fixture); \
300   BENCHMARK_TEMPLATE(BM_ErrorStringRepeatedly, fixture); \
301   BENCHMARK_TEMPLATE(BM_ErrorGetStatus, fixture);        \
302   BENCHMARK_TEMPLATE(BM_ErrorGetStatusCode, fixture);    \
303   BENCHMARK_TEMPLATE(BM_ErrorHttpError, fixture);        \
304   BENCHMARK_TEMPLATE(BM_HasClearGrpcStatus, fixture)
305 
306 BENCHMARK_SUITE(ErrorNone);
307 BENCHMARK_SUITE(ErrorCancelled);
308 BENCHMARK_SUITE(SimpleError);
309 BENCHMARK_SUITE(ErrorWithGrpcStatus);
310 BENCHMARK_SUITE(ErrorWithHttpError);
311 BENCHMARK_SUITE(ErrorWithNestedGrpcStatus);
312 
313 // Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
314 // and others do not. This allows us to support both modes.
315 namespace benchmark {
RunTheBenchmarksNamespaced()316 void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
317 }  // namespace benchmark
318 
main(int argc,char ** argv)319 int main(int argc, char** argv) {
320   grpc::testing::TestEnvironment env(argc, argv);
321   LibraryInitializer libInit;
322   ::benchmark::Initialize(&argc, argv);
323   ::grpc::testing::InitTest(&argc, &argv, false);
324   benchmark::RunTheBenchmarksNamespaced();
325   return 0;
326 }
327