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