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"
32 void operator()(grpc_error* error) { GRPC_ERROR_UNREF(error); }
34 typedef std::unique_ptr<grpc_error, ErrorDeleter> ErrorPtr;
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"));
41 track_counters.Finish(state);
43 BENCHMARK(BM_ErrorCreateFromStatic);
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"));
50 track_counters.Finish(state);
52 BENCHMARK(BM_ErrorCreateFromCopied);
54 static void BM_ErrorCreateAndSetStatus(benchmark::State& state) {
55 TrackCounters track_counters;
56 while (state.KeepRunning()) {
58 grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"),
59 GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_ABORTED));
61 track_counters.Finish(state);
63 BENCHMARK(BM_ErrorCreateAndSetStatus);
65 static void BM_ErrorCreateAndSetIntAndStr(benchmark::State& state) {
66 TrackCounters track_counters;
67 while (state.KeepRunning()) {
68 GRPC_ERROR_UNREF(grpc_error_set_str(
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")));
74 track_counters.Finish(state);
76 BENCHMARK(BM_ErrorCreateAndSetIntAndStr);
78 static void BM_ErrorCreateAndSetIntLoop(benchmark::State& state) {
79 TrackCounters track_counters;
80 grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error");
82 while (state.KeepRunning()) {
83 error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, n++);
85 GRPC_ERROR_UNREF(error);
86 track_counters.Finish(state);
88 BENCHMARK(BM_ErrorCreateAndSetIntLoop);
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));
98 GRPC_ERROR_UNREF(error);
99 track_counters.Finish(state);
101 BENCHMARK(BM_ErrorCreateAndSetStrLoop);
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));
109 GRPC_ERROR_UNREF(error);
110 track_counters.Finish(state);
112 BENCHMARK(BM_ErrorRefUnref);
114 static void BM_ErrorUnrefNone(benchmark::State& state) {
115 TrackCounters track_counters;
116 while (state.KeepRunning()) {
117 GRPC_ERROR_UNREF(GRPC_ERROR_NONE);
120 BENCHMARK(BM_ErrorUnrefNone);
122 static void BM_ErrorGetIntFromNoError(benchmark::State& state) {
123 TrackCounters track_counters;
124 while (state.KeepRunning()) {
126 grpc_error_get_int(GRPC_ERROR_NONE, GRPC_ERROR_INT_GRPC_STATUS, &value);
128 track_counters.Finish(state);
130 BENCHMARK(BM_ErrorGetIntFromNoError);
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()) {
138 grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
140 track_counters.Finish(state);
142 BENCHMARK(BM_ErrorGetMissingInt);
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()) {
150 grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
152 track_counters.Finish(state);
154 BENCHMARK(BM_ErrorGetPresentInt);
156 // Fixtures for tests: generate different kinds of errors
159 grpc_millis deadline() const { return deadline_; }
160 grpc_error* error() const { return GRPC_ERROR_NONE; }
163 const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
166 class ErrorCancelled {
168 grpc_millis deadline() const { return deadline_; }
169 grpc_error* error() const { return GRPC_ERROR_CANCELLED; }
172 const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
177 grpc_millis deadline() const { return deadline_; }
178 grpc_error* error() const { return error_.get(); }
181 const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE;
182 ErrorPtr error_{GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error")};
185 class ErrorWithGrpcStatus {
187 grpc_millis deadline() const { return deadline_; }
188 grpc_error* error() const { return error_.get(); }
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)};
197 class ErrorWithHttpError {
199 grpc_millis deadline() const { return deadline_; }
200 grpc_error* error() const { return error_.get(); }
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)};
209 class ErrorWithNestedGrpcStatus {
211 grpc_millis deadline() const { return deadline_; }
212 grpc_error* error() const { return error_.get(); }
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)};
224 template <class Fixture>
225 static void BM_ErrorStringOnNewError(benchmark::State& state) {
226 TrackCounters track_counters;
227 while (state.KeepRunning()) {
229 grpc_error_string(fixture.error());
231 track_counters.Finish(state);
234 template <class Fixture>
235 static void BM_ErrorStringRepeatedly(benchmark::State& state) {
236 TrackCounters track_counters;
238 while (state.KeepRunning()) {
239 grpc_error_string(fixture.error());
241 track_counters.Finish(state);
244 template <class Fixture>
245 static void BM_ErrorGetStatus(benchmark::State& state) {
246 TrackCounters track_counters;
248 grpc_core::ExecCtx exec_ctx;
249 while (state.KeepRunning()) {
250 grpc_status_code status;
252 grpc_error_get_status(fixture.error(), fixture.deadline(), &status, &slice,
256 track_counters.Finish(state);
259 template <class Fixture>
260 static void BM_ErrorGetStatusCode(benchmark::State& state) {
261 TrackCounters track_counters;
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,
270 track_counters.Finish(state);
273 template <class Fixture>
274 static void BM_ErrorHttpError(benchmark::State& state) {
275 TrackCounters track_counters;
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,
284 track_counters.Finish(state);
287 template <class Fixture>
288 static void BM_HasClearGrpcStatus(benchmark::State& state) {
289 TrackCounters track_counters;
291 while (state.KeepRunning()) {
292 grpc_error_has_clear_grpc_status(fixture.error());
294 track_counters.Finish(state);
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)
305 BENCHMARK_SUITE(ErrorNone);
306 BENCHMARK_SUITE(ErrorCancelled);
307 BENCHMARK_SUITE(SimpleError);
308 BENCHMARK_SUITE(ErrorWithGrpcStatus);
309 BENCHMARK_SUITE(ErrorWithHttpError);
310 BENCHMARK_SUITE(ErrorWithNestedGrpcStatus);
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
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();