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