3 * Copyright 2015 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 /* Test various operations on grpc_error */
21 #include <benchmark/benchmark.h>
24 #include "src/core/lib/iomgr/error.h"
25 #include "src/core/lib/transport/error_utils.h"
27 #include "test/cpp/microbenchmarks/helpers.h"
28 #include "test/cpp/util/test_config.h"
30 auto& force_library_initialization = Library::get();
34 void operator()(grpc_error* error) { GRPC_ERROR_UNREF(error); }
36 typedef std::unique_ptr<grpc_error, ErrorDeleter> ErrorPtr;
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"));
43 track_counters.Finish(state);
45 BENCHMARK(BM_ErrorCreateFromStatic);
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"));
52 track_counters.Finish(state);
54 BENCHMARK(BM_ErrorCreateFromCopied);
56 static void BM_ErrorCreateAndSetStatus(benchmark::State& state) {
57 TrackCounters track_counters;
58 while (state.KeepRunning()) {
60 grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"),
61 GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_ABORTED));
63 track_counters.Finish(state);
65 BENCHMARK(BM_ErrorCreateAndSetStatus);
67 static void BM_ErrorCreateAndSetIntAndStr(benchmark::State& state) {
68 TrackCounters track_counters;
69 while (state.KeepRunning()) {
70 GRPC_ERROR_UNREF(grpc_error_set_str(
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")));
76 track_counters.Finish(state);
78 BENCHMARK(BM_ErrorCreateAndSetIntAndStr);
80 static void BM_ErrorCreateAndSetIntLoop(benchmark::State& state) {
81 TrackCounters track_counters;
82 grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error");
84 while (state.KeepRunning()) {
85 error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, n++);
87 GRPC_ERROR_UNREF(error);
88 track_counters.Finish(state);
90 BENCHMARK(BM_ErrorCreateAndSetIntLoop);
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));
100 GRPC_ERROR_UNREF(error);
101 track_counters.Finish(state);
103 BENCHMARK(BM_ErrorCreateAndSetStrLoop);
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));
111 GRPC_ERROR_UNREF(error);
112 track_counters.Finish(state);
114 BENCHMARK(BM_ErrorRefUnref);
116 static void BM_ErrorUnrefNone(benchmark::State& state) {
117 TrackCounters track_counters;
118 while (state.KeepRunning()) {
119 GRPC_ERROR_UNREF(GRPC_ERROR_NONE);
122 BENCHMARK(BM_ErrorUnrefNone);
124 static void BM_ErrorGetIntFromNoError(benchmark::State& state) {
125 TrackCounters track_counters;
126 while (state.KeepRunning()) {
128 grpc_error_get_int(GRPC_ERROR_NONE, GRPC_ERROR_INT_GRPC_STATUS, &value);
130 track_counters.Finish(state);
132 BENCHMARK(BM_ErrorGetIntFromNoError);
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()) {
140 grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
142 track_counters.Finish(state);
144 BENCHMARK(BM_ErrorGetMissingInt);
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()) {
152 grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
154 track_counters.Finish(state);
156 BENCHMARK(BM_ErrorGetPresentInt);
158 // Fixtures for tests: generate different kinds of errors
161 grpc_millis deadline() const { return deadline_; }
162 grpc_error* error() const { return GRPC_ERROR_NONE; }
165 const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
168 class ErrorCancelled {
170 grpc_millis deadline() const { return deadline_; }
171 grpc_error* error() const { return GRPC_ERROR_CANCELLED; }
174 const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
179 grpc_millis deadline() const { return deadline_; }
180 grpc_error* error() const { return error_.get(); }
183 const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
184 ErrorPtr error_{GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error")};
187 class ErrorWithGrpcStatus {
189 grpc_millis deadline() const { return deadline_; }
190 grpc_error* error() const { return error_.get(); }
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)};
199 class ErrorWithHttpError {
201 grpc_millis deadline() const { return deadline_; }
202 grpc_error* error() const { return error_.get(); }
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)};
211 class ErrorWithNestedGrpcStatus {
213 grpc_millis deadline() const { return deadline_; }
214 grpc_error* error() const { return error_.get(); }
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)};
226 template <class Fixture>
227 static void BM_ErrorStringOnNewError(benchmark::State& state) {
228 TrackCounters track_counters;
229 while (state.KeepRunning()) {
231 grpc_error_string(fixture.error());
233 track_counters.Finish(state);
236 template <class Fixture>
237 static void BM_ErrorStringRepeatedly(benchmark::State& state) {
238 TrackCounters track_counters;
240 while (state.KeepRunning()) {
241 grpc_error_string(fixture.error());
243 track_counters.Finish(state);
246 template <class Fixture>
247 static void BM_ErrorGetStatus(benchmark::State& state) {
248 TrackCounters track_counters;
250 grpc_core::ExecCtx exec_ctx;
251 while (state.KeepRunning()) {
252 grpc_status_code status;
254 grpc_error_get_status(fixture.error(), fixture.deadline(), &status, &slice,
258 track_counters.Finish(state);
261 template <class Fixture>
262 static void BM_ErrorGetStatusCode(benchmark::State& state) {
263 TrackCounters track_counters;
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,
272 track_counters.Finish(state);
275 template <class Fixture>
276 static void BM_ErrorHttpError(benchmark::State& state) {
277 TrackCounters track_counters;
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,
286 track_counters.Finish(state);
289 template <class Fixture>
290 static void BM_HasClearGrpcStatus(benchmark::State& state) {
291 TrackCounters track_counters;
293 while (state.KeepRunning()) {
294 grpc_error_has_clear_grpc_status(fixture.error());
296 track_counters.Finish(state);
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)
307 BENCHMARK_SUITE(ErrorNone);
308 BENCHMARK_SUITE(ErrorCancelled);
309 BENCHMARK_SUITE(SimpleError);
310 BENCHMARK_SUITE(ErrorWithGrpcStatus);
311 BENCHMARK_SUITE(ErrorWithHttpError);
312 BENCHMARK_SUITE(ErrorWithNestedGrpcStatus);
314 // Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
315 // and others do not. This allows us to support both modes.
316 namespace benchmark {
317 void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
318 } // namespace benchmark
320 int main(int argc, char** argv) {
321 ::benchmark::Initialize(&argc, argv);
322 ::grpc::testing::InitTest(&argc, &argv, false);
323 benchmark::RunTheBenchmarksNamespaced();