mirror of https://github.com/grpc/grpc.git
The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
9.7 KiB
324 lines
9.7 KiB
/* |
|
* |
|
* Copyright 2015 gRPC authors. |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
* |
|
*/ |
|
|
|
/* Test various operations on grpc_error */ |
|
|
|
#include <benchmark/benchmark.h> |
|
#include <memory> |
|
|
|
#include "src/core/lib/iomgr/error.h" |
|
#include "src/core/lib/transport/error_utils.h" |
|
|
|
#include "test/cpp/microbenchmarks/helpers.h" |
|
#include "test/cpp/util/test_config.h" |
|
|
|
class ErrorDeleter { |
|
public: |
|
void operator()(grpc_error* error) { GRPC_ERROR_UNREF(error); } |
|
}; |
|
typedef std::unique_ptr<grpc_error, ErrorDeleter> ErrorPtr; |
|
|
|
static void BM_ErrorCreateFromStatic(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
for (auto _ : state) { |
|
GRPC_ERROR_UNREF(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error")); |
|
} |
|
track_counters.Finish(state); |
|
} |
|
BENCHMARK(BM_ErrorCreateFromStatic); |
|
|
|
static void BM_ErrorCreateFromCopied(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
for (auto _ : state) { |
|
GRPC_ERROR_UNREF(GRPC_ERROR_CREATE_FROM_COPIED_STRING("Error not inline")); |
|
} |
|
track_counters.Finish(state); |
|
} |
|
BENCHMARK(BM_ErrorCreateFromCopied); |
|
|
|
static void BM_ErrorCreateAndSetStatus(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
for (auto _ : state) { |
|
GRPC_ERROR_UNREF( |
|
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), |
|
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_ABORTED)); |
|
} |
|
track_counters.Finish(state); |
|
} |
|
BENCHMARK(BM_ErrorCreateAndSetStatus); |
|
|
|
static void BM_ErrorCreateAndSetIntAndStr(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
for (auto _ : state) { |
|
GRPC_ERROR_UNREF(grpc_error_set_str( |
|
grpc_error_set_int( |
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("GOAWAY received"), |
|
GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)0), |
|
GRPC_ERROR_STR_RAW_BYTES, grpc_slice_from_static_string("raw bytes"))); |
|
} |
|
track_counters.Finish(state); |
|
} |
|
BENCHMARK(BM_ErrorCreateAndSetIntAndStr); |
|
|
|
static void BM_ErrorCreateAndSetIntLoop(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"); |
|
int n = 0; |
|
for (auto _ : state) { |
|
error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, n++); |
|
} |
|
GRPC_ERROR_UNREF(error); |
|
track_counters.Finish(state); |
|
} |
|
BENCHMARK(BM_ErrorCreateAndSetIntLoop); |
|
|
|
static void BM_ErrorCreateAndSetStrLoop(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"); |
|
const char* str = "hello"; |
|
for (auto _ : state) { |
|
error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, |
|
grpc_slice_from_static_string(str)); |
|
} |
|
GRPC_ERROR_UNREF(error); |
|
track_counters.Finish(state); |
|
} |
|
BENCHMARK(BM_ErrorCreateAndSetStrLoop); |
|
|
|
static void BM_ErrorRefUnref(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"); |
|
for (auto _ : state) { |
|
GRPC_ERROR_UNREF(GRPC_ERROR_REF(error)); |
|
} |
|
GRPC_ERROR_UNREF(error); |
|
track_counters.Finish(state); |
|
} |
|
BENCHMARK(BM_ErrorRefUnref); |
|
|
|
static void BM_ErrorUnrefNone(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
for (auto _ : state) { |
|
GRPC_ERROR_UNREF(GRPC_ERROR_NONE); |
|
} |
|
} |
|
BENCHMARK(BM_ErrorUnrefNone); |
|
|
|
static void BM_ErrorGetIntFromNoError(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
for (auto _ : state) { |
|
intptr_t value; |
|
grpc_error_get_int(GRPC_ERROR_NONE, GRPC_ERROR_INT_GRPC_STATUS, &value); |
|
} |
|
track_counters.Finish(state); |
|
} |
|
BENCHMARK(BM_ErrorGetIntFromNoError); |
|
|
|
static void BM_ErrorGetMissingInt(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
ErrorPtr error(grpc_error_set_int( |
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_INDEX, 1)); |
|
for (auto _ : state) { |
|
intptr_t value; |
|
grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value); |
|
} |
|
track_counters.Finish(state); |
|
} |
|
BENCHMARK(BM_ErrorGetMissingInt); |
|
|
|
static void BM_ErrorGetPresentInt(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
ErrorPtr error(grpc_error_set_int( |
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_OFFSET, 1)); |
|
for (auto _ : state) { |
|
intptr_t value; |
|
grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value); |
|
} |
|
track_counters.Finish(state); |
|
} |
|
BENCHMARK(BM_ErrorGetPresentInt); |
|
|
|
// Fixtures for tests: generate different kinds of errors |
|
class ErrorNone { |
|
public: |
|
grpc_millis deadline() const { return deadline_; } |
|
grpc_error* error() const { return GRPC_ERROR_NONE; } |
|
|
|
private: |
|
const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; |
|
}; |
|
|
|
class ErrorCancelled { |
|
public: |
|
grpc_millis deadline() const { return deadline_; } |
|
grpc_error* error() const { return GRPC_ERROR_CANCELLED; } |
|
|
|
private: |
|
const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; |
|
}; |
|
|
|
class SimpleError { |
|
public: |
|
grpc_millis deadline() const { return deadline_; } |
|
grpc_error* error() const { return error_.get(); } |
|
|
|
private: |
|
const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; |
|
ErrorPtr error_{GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error")}; |
|
}; |
|
|
|
class ErrorWithGrpcStatus { |
|
public: |
|
grpc_millis deadline() const { return deadline_; } |
|
grpc_error* error() const { return error_.get(); } |
|
|
|
private: |
|
const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; |
|
ErrorPtr error_{grpc_error_set_int( |
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_GRPC_STATUS, |
|
GRPC_STATUS_UNIMPLEMENTED)}; |
|
}; |
|
|
|
class ErrorWithHttpError { |
|
public: |
|
grpc_millis deadline() const { return deadline_; } |
|
grpc_error* error() const { return error_.get(); } |
|
|
|
private: |
|
const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; |
|
ErrorPtr error_{grpc_error_set_int( |
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_HTTP2_ERROR, |
|
GRPC_HTTP2_COMPRESSION_ERROR)}; |
|
}; |
|
|
|
class ErrorWithNestedGrpcStatus { |
|
public: |
|
grpc_millis deadline() const { return deadline_; } |
|
grpc_error* error() const { return error_.get(); } |
|
|
|
private: |
|
const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; |
|
ErrorPtr nested_error_{grpc_error_set_int( |
|
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_GRPC_STATUS, |
|
GRPC_STATUS_UNIMPLEMENTED)}; |
|
grpc_error* nested_errors_[1] = {nested_error_.get()}; |
|
ErrorPtr error_{GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( |
|
"Error", nested_errors_, 1)}; |
|
}; |
|
|
|
template <class Fixture> |
|
static void BM_ErrorStringOnNewError(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
for (auto _ : state) { |
|
Fixture fixture; |
|
grpc_error_string(fixture.error()); |
|
} |
|
track_counters.Finish(state); |
|
} |
|
|
|
template <class Fixture> |
|
static void BM_ErrorStringRepeatedly(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
Fixture fixture; |
|
for (auto _ : state) { |
|
grpc_error_string(fixture.error()); |
|
} |
|
track_counters.Finish(state); |
|
} |
|
|
|
template <class Fixture> |
|
static void BM_ErrorGetStatus(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
Fixture fixture; |
|
grpc_core::ExecCtx exec_ctx; |
|
for (auto _ : state) { |
|
grpc_status_code status; |
|
grpc_slice slice; |
|
grpc_error_get_status(fixture.error(), fixture.deadline(), &status, &slice, |
|
nullptr, nullptr); |
|
} |
|
|
|
track_counters.Finish(state); |
|
} |
|
|
|
template <class Fixture> |
|
static void BM_ErrorGetStatusCode(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
Fixture fixture; |
|
grpc_core::ExecCtx exec_ctx; |
|
for (auto _ : state) { |
|
grpc_status_code status; |
|
grpc_error_get_status(fixture.error(), fixture.deadline(), &status, nullptr, |
|
nullptr, nullptr); |
|
} |
|
|
|
track_counters.Finish(state); |
|
} |
|
|
|
template <class Fixture> |
|
static void BM_ErrorHttpError(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
Fixture fixture; |
|
grpc_core::ExecCtx exec_ctx; |
|
for (auto _ : state) { |
|
grpc_http2_error_code error; |
|
grpc_error_get_status(fixture.error(), fixture.deadline(), nullptr, nullptr, |
|
&error, nullptr); |
|
} |
|
|
|
track_counters.Finish(state); |
|
} |
|
|
|
template <class Fixture> |
|
static void BM_HasClearGrpcStatus(benchmark::State& state) { |
|
TrackCounters track_counters; |
|
Fixture fixture; |
|
for (auto _ : state) { |
|
grpc_error_has_clear_grpc_status(fixture.error()); |
|
} |
|
track_counters.Finish(state); |
|
} |
|
|
|
#define BENCHMARK_SUITE(fixture) \ |
|
BENCHMARK_TEMPLATE(BM_ErrorStringOnNewError, fixture); \ |
|
BENCHMARK_TEMPLATE(BM_ErrorStringRepeatedly, fixture); \ |
|
BENCHMARK_TEMPLATE(BM_ErrorGetStatus, fixture); \ |
|
BENCHMARK_TEMPLATE(BM_ErrorGetStatusCode, fixture); \ |
|
BENCHMARK_TEMPLATE(BM_ErrorHttpError, fixture); \ |
|
BENCHMARK_TEMPLATE(BM_HasClearGrpcStatus, fixture) |
|
|
|
BENCHMARK_SUITE(ErrorNone); |
|
BENCHMARK_SUITE(ErrorCancelled); |
|
BENCHMARK_SUITE(SimpleError); |
|
BENCHMARK_SUITE(ErrorWithGrpcStatus); |
|
BENCHMARK_SUITE(ErrorWithHttpError); |
|
BENCHMARK_SUITE(ErrorWithNestedGrpcStatus); |
|
|
|
// Some distros have RunSpecifiedBenchmarks under the benchmark namespace, |
|
// and others do not. This allows us to support both modes. |
|
namespace benchmark { |
|
void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); } |
|
} // namespace benchmark |
|
|
|
int main(int argc, char** argv) { |
|
LibraryInitializer libInit; |
|
::benchmark::Initialize(&argc, argv); |
|
::grpc::testing::InitTest(&argc, &argv, false); |
|
benchmark::RunTheBenchmarksNamespaced(); |
|
return 0; |
|
}
|
|
|