diff options
Diffstat (limited to 'test/cpp')
-rw-r--r-- | test/cpp/end2end/end2end_test.cc | 3 | ||||
-rw-r--r-- | test/cpp/end2end/test_service_impl.cc | 4 | ||||
-rw-r--r-- | test/cpp/microbenchmarks/bm_chttp2_hpack.cc | 443 | ||||
-rw-r--r-- | test/cpp/microbenchmarks/bm_cq.cc | 26 | ||||
-rw-r--r-- | test/cpp/microbenchmarks/bm_metadata.cc | 282 | ||||
-rw-r--r-- | test/cpp/microbenchmarks/representative_server_initial_metadata.headers | 4 | ||||
-rw-r--r-- | test/cpp/microbenchmarks/representative_server_trailing_metadata.headers | 3 |
7 files changed, 763 insertions, 2 deletions
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 47e5c5bd77..df78557c43 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -901,8 +901,7 @@ TEST_P(End2endTest, RpcMaxMessageSize) { EchoRequest request; EchoResponse response; request.set_message(string(kMaxMessageSize_ * 2, 'a')); - // cancelled is not guaranteed to appear before the end of the service handler - request.mutable_param()->set_skip_cancelled_check(true); + request.mutable_param()->set_server_die(true); ClientContext context; Status s = stub_->Echo(&context, request, &response); diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc index 001047778d..59d36e9cb5 100644 --- a/test/cpp/end2end/test_service_impl.cc +++ b/test/cpp/end2end/test_service_impl.cc @@ -88,6 +88,10 @@ void CheckServerAuthContext( Status TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) { + if (request->has_param() && request->param().server_die()) { + gpr_log(GPR_ERROR, "The request should not reach application handler."); + GPR_ASSERT(0); + } int server_try_cancel = GetIntValueFromMetadata( kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); if (server_try_cancel > DO_NOT_CANCEL) { diff --git a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc new file mode 100644 index 0000000000..5fb3f37130 --- /dev/null +++ b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc @@ -0,0 +1,443 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* Microbenchmarks around CHTTP2 HPACK operations */ + +#include <grpc/support/log.h> +#include <string.h> +#include <sstream> +extern "C" { +#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h" +#include "src/core/ext/transport/chttp2/transport/hpack_parser.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/static_metadata.h" +} +#include "third_party/benchmark/include/benchmark/benchmark.h" + +static struct Init { + Init() { grpc_init(); } + ~Init() { grpc_shutdown(); } +} g_init; + +//////////////////////////////////////////////////////////////////////////////// +// HPACK encoder +// + +static void BM_HpackEncoderInitDestroy(benchmark::State &state) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_chttp2_hpack_compressor c; + while (state.KeepRunning()) { + grpc_chttp2_hpack_compressor_init(&c); + grpc_chttp2_hpack_compressor_destroy(&exec_ctx, &c); + grpc_exec_ctx_flush(&exec_ctx); + } + grpc_exec_ctx_finish(&exec_ctx); +} +BENCHMARK(BM_HpackEncoderInitDestroy); + +template <class Fixture> +static void BM_HpackEncoderEncodeHeader(benchmark::State &state) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + + grpc_metadata_batch b; + grpc_metadata_batch_init(&b); + std::vector<grpc_mdelem> elems = Fixture::GetElems(&exec_ctx); + std::vector<grpc_linked_mdelem> storage(elems.size()); + for (size_t i = 0; i < elems.size(); i++) { + GPR_ASSERT(GRPC_LOG_IF_ERROR( + "addmd", + grpc_metadata_batch_add_tail(&exec_ctx, &b, &storage[i], elems[i]))); + } + + grpc_chttp2_hpack_compressor c; + grpc_chttp2_hpack_compressor_init(&c); + grpc_transport_one_way_stats stats; + memset(&stats, 0, sizeof(stats)); + grpc_slice_buffer outbuf; + grpc_slice_buffer_init(&outbuf); + while (state.KeepRunning()) { + grpc_chttp2_encode_header(&exec_ctx, &c, (uint32_t)state.iterations(), &b, + state.range(0), state.range(1), &stats, &outbuf); + grpc_slice_buffer_reset_and_unref_internal(&exec_ctx, &outbuf); + grpc_exec_ctx_flush(&exec_ctx); + } + grpc_metadata_batch_destroy(&exec_ctx, &b); + grpc_chttp2_hpack_compressor_destroy(&exec_ctx, &c); + grpc_slice_buffer_destroy_internal(&exec_ctx, &outbuf); + grpc_exec_ctx_finish(&exec_ctx); + + std::ostringstream label; + label << "framing_bytes/iter:" << (static_cast<double>(stats.framing_bytes) / + static_cast<double>(state.iterations())) + << " header_bytes/iter:" << (static_cast<double>(stats.header_bytes) / + static_cast<double>(state.iterations())); + state.SetLabel(label.str()); +} + +namespace hpack_encoder_fixtures { + +class EmptyBatch { + public: + static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { + return {}; + } +}; + +class SingleStaticElem { + public: + static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { + return {GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE}; + } +}; + +class SingleInternedElem { + public: + static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { + return {grpc_mdelem_from_slices( + exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("abc")), + grpc_slice_intern(grpc_slice_from_static_string("def")))}; + } +}; + +class SingleInternedKeyElem { + public: + static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { + return {grpc_mdelem_from_slices( + exec_ctx, grpc_slice_intern(grpc_slice_from_static_string("abc")), + grpc_slice_from_static_string("def"))}; + } +}; + +class SingleNonInternedElem { + public: + static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { + return {grpc_mdelem_from_slices(exec_ctx, + grpc_slice_from_static_string("abc"), + grpc_slice_from_static_string("def"))}; + } +}; + +class RepresentativeClientInitialMetadata { + public: + static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { + return { + GRPC_MDELEM_SCHEME_HTTP, GRPC_MDELEM_METHOD_POST, + grpc_mdelem_from_slices( + exec_ctx, GRPC_MDSTR_PATH, + grpc_slice_intern(grpc_slice_from_static_string("/foo/bar"))), + grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_AUTHORITY, + grpc_slice_intern(grpc_slice_from_static_string( + "foo.test.google.fr:1234"))), + GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP, + GRPC_MDELEM_TE_TRAILERS, + GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC, + grpc_mdelem_from_slices( + exec_ctx, GRPC_MDSTR_USER_AGENT, + grpc_slice_intern(grpc_slice_from_static_string( + "grpc-c/3.0.0-dev (linux; chttp2; green)")))}; + } +}; + +class RepresentativeServerInitialMetadata { + public: + static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { + return {GRPC_MDELEM_STATUS_200, + GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC, + GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP}; + } +}; + +class RepresentativeServerTrailingMetadata { + public: + static std::vector<grpc_mdelem> GetElems(grpc_exec_ctx *exec_ctx) { + return {GRPC_MDELEM_GRPC_STATUS_0}; + } +}; + +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, EmptyBatch)->Args({0, 16384}); +// test with eof (shouldn't affect anything) +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, EmptyBatch)->Args({1, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleStaticElem) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleInternedKeyElem) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleInternedElem) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonInternedElem) + ->Args({0, 16384}); +// test with a tiny frame size, to highlight continuation costs +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonInternedElem) + ->Args({0, 1}); + +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, + RepresentativeClientInitialMetadata) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, + RepresentativeServerInitialMetadata) + ->Args({0, 16384}); +BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, + RepresentativeServerTrailingMetadata) + ->Args({1, 16384}); + +} // namespace hpack_encoder_fixtures + +//////////////////////////////////////////////////////////////////////////////// +// HPACK parser +// + +static void BM_HpackParserInitDestroy(benchmark::State &state) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_chttp2_hpack_parser p; + while (state.KeepRunning()) { + grpc_chttp2_hpack_parser_init(&exec_ctx, &p); + grpc_chttp2_hpack_parser_destroy(&exec_ctx, &p); + grpc_exec_ctx_flush(&exec_ctx); + } + grpc_exec_ctx_finish(&exec_ctx); +} +BENCHMARK(BM_HpackParserInitDestroy); + +static void UnrefHeader(grpc_exec_ctx *exec_ctx, void *user_data, + grpc_mdelem md) { + GRPC_MDELEM_UNREF(exec_ctx, md); +} + +template <class Fixture> +static void BM_HpackParserParseHeader(benchmark::State &state) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + std::vector<grpc_slice> init_slices = Fixture::GetInitSlices(); + std::vector<grpc_slice> benchmark_slices = Fixture::GetBenchmarkSlices(); + grpc_chttp2_hpack_parser p; + grpc_chttp2_hpack_parser_init(&exec_ctx, &p); + p.on_header = UnrefHeader; + p.on_header_user_data = nullptr; + for (auto slice : init_slices) { + grpc_chttp2_hpack_parser_parse(&exec_ctx, &p, slice); + } + while (state.KeepRunning()) { + for (auto slice : benchmark_slices) { + grpc_chttp2_hpack_parser_parse(&exec_ctx, &p, slice); + } + grpc_exec_ctx_flush(&exec_ctx); + } + grpc_chttp2_hpack_parser_destroy(&exec_ctx, &p); + grpc_exec_ctx_finish(&exec_ctx); +} + +namespace hpack_parser_fixtures { + +static grpc_slice MakeSlice(std::initializer_list<uint8_t> bytes) { + grpc_slice s = grpc_slice_malloc(bytes.size()); + uint8_t *p = GRPC_SLICE_START_PTR(s); + for (auto b : bytes) { + *p++ = b; + } + return s; +} + +class EmptyBatch { + public: + static std::vector<grpc_slice> GetInitSlices() { return {}; } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice({})}; + } +}; + +class IndexedSingleStaticElem { + public: + static std::vector<grpc_slice> GetInitSlices() { + return {MakeSlice( + {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})}; + } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice({0xbe})}; + } +}; + +class AddIndexedSingleStaticElem { + public: + static std::vector<grpc_slice> GetInitSlices() { return {}; } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice( + {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})}; + } +}; + +class KeyIndexedSingleStaticElem { + public: + static std::vector<grpc_slice> GetInitSlices() { + return {MakeSlice( + {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})}; + } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice({0x7e, 0x03, 'd', 'e', 'f'})}; + } +}; + +class IndexedSingleInternedElem { + public: + static std::vector<grpc_slice> GetInitSlices() { + return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})}; + } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice({0xbe})}; + } +}; + +class AddIndexedSingleInternedElem { + public: + static std::vector<grpc_slice> GetInitSlices() { return {}; } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})}; + } +}; + +class KeyIndexedSingleInternedElem { + public: + static std::vector<grpc_slice> GetInitSlices() { + return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})}; + } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice({0x7e, 0x03, 'g', 'h', 'i'})}; + } +}; + +class NonIndexedElem { + public: + static std::vector<grpc_slice> GetInitSlices() { return {}; } + static std::vector<grpc_slice> GetBenchmarkSlices() { + return {MakeSlice({0x00, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})}; + } +}; + +class RepresentativeClientInitialMetadata { + public: + static std::vector<grpc_slice> GetInitSlices() { + return {grpc_slice_from_static_string( + // generated with: + // ``` + // tools/codegen/core/gen_header_frame.py --compression inc --no_framing + // < test/core/bad_client/tests/simple_request.headers + // ``` + "@\x05:path\x08/foo/bar" + "@\x07:scheme\x04http" + "@\x07:method\x04POST" + "@\x0a:authority\x09localhost" + "@\x0c" + "content-type\x10" + "application/grpc" + "@\x14grpc-accept-encoding\x15identity,deflate,gzip" + "@\x02te\x08trailers" + "@\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)")}; + } + static std::vector<grpc_slice> GetBenchmarkSlices() { + // generated with: + // ``` + // tools/codegen/core/gen_header_frame.py --compression pre --no_framing + // --hex < test/core/bad_client/tests/simple_request.headers + // ``` + return {MakeSlice({0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe})}; + } +}; + +class RepresentativeServerInitialMetadata { + public: + static std::vector<grpc_slice> GetInitSlices() { + return {grpc_slice_from_static_string( + // generated with: + // ``` + // tools/codegen/core/gen_header_frame.py --compression inc --no_framing + // < + // test/cpp/microbenchmarks/representative_server_initial_metadata.headers + // ``` + "@\x07:status\x03" + "200" + "@\x0c" + "content-type\x10" + "application/grpc" + "@\x14grpc-accept-encoding\x15identity,deflate,gzip")}; + } + static std::vector<grpc_slice> GetBenchmarkSlices() { + // generated with: + // ``` + // tools/codegen/core/gen_header_frame.py --compression pre --no_framing + // --hex < + // test/cpp/microbenchmarks/representative_server_initial_metadata.headers + // ``` + return {MakeSlice({0xc0, 0xbf, 0xbe})}; + } +}; + +class RepresentativeServerTrailingMetadata { + public: + static std::vector<grpc_slice> GetInitSlices() { + return {grpc_slice_from_static_string( + // generated with: + // ``` + // tools/codegen/core/gen_header_frame.py --compression inc --no_framing + // < + // test/cpp/microbenchmarks/representative_server_trailing_metadata.headers + // ``` + "@\x0bgrpc-status\x01" + "0" + "@\x0cgrpc-message\x00")}; + } + static std::vector<grpc_slice> GetBenchmarkSlices() { + // generated with: + // ``` + // tools/codegen/core/gen_header_frame.py --compression pre --no_framing + // --hex < + // test/cpp/microbenchmarks/representative_server_trailing_metadata.headers + // ``` + return {MakeSlice({0xbf, 0xbe})}; + } +}; + +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, EmptyBatch); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleStaticElem); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleStaticElem); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleStaticElem); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleInternedElem); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleInternedElem); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleInternedElem); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedElem); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, + RepresentativeClientInitialMetadata); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, + RepresentativeServerInitialMetadata); +BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, + RepresentativeServerTrailingMetadata); + +} // namespace hpack_parser_fixtures + +BENCHMARK_MAIN(); diff --git a/test/cpp/microbenchmarks/bm_cq.cc b/test/cpp/microbenchmarks/bm_cq.cc index 195dcef3ab..c017474bf4 100644 --- a/test/cpp/microbenchmarks/bm_cq.cc +++ b/test/cpp/microbenchmarks/bm_cq.cc @@ -113,6 +113,32 @@ static void BM_Pass1Core(benchmark::State& state) { } BENCHMARK(BM_Pass1Core); +static void BM_Pluck1Core(benchmark::State& state) { + grpc_completion_queue* cq = grpc_completion_queue_create(NULL); + gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); + while (state.KeepRunning()) { + grpc_cq_completion completion; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_cq_begin_op(cq, NULL); + grpc_cq_end_op(&exec_ctx, cq, NULL, GRPC_ERROR_NONE, + DoneWithCompletionOnStack, NULL, &completion); + grpc_exec_ctx_finish(&exec_ctx); + grpc_completion_queue_pluck(cq, NULL, deadline, NULL); + } + grpc_completion_queue_destroy(cq); +} +BENCHMARK(BM_Pluck1Core); + +static void BM_EmptyCore(benchmark::State& state) { + grpc_completion_queue* cq = grpc_completion_queue_create(NULL); + gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC); + while (state.KeepRunning()) { + grpc_completion_queue_next(cq, deadline, NULL); + } + grpc_completion_queue_destroy(cq); +} +BENCHMARK(BM_EmptyCore); + } // namespace testing } // namespace grpc diff --git a/test/cpp/microbenchmarks/bm_metadata.cc b/test/cpp/microbenchmarks/bm_metadata.cc new file mode 100644 index 0000000000..7f81fbabcc --- /dev/null +++ b/test/cpp/microbenchmarks/bm_metadata.cc @@ -0,0 +1,282 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* Test out various metadata handling primitives */ + +#include <grpc/grpc.h> + +extern "C" { +#include "src/core/lib/transport/metadata.h" +#include "src/core/lib/transport/static_metadata.h" +} + +#include "third_party/benchmark/include/benchmark/benchmark.h" + +static class InitializeStuff { + public: + InitializeStuff() { grpc_init(); } + ~InitializeStuff() { grpc_shutdown(); } +} initialize_stuff; + +static void BM_SliceFromStatic(benchmark::State& state) { + while (state.KeepRunning()) { + benchmark::DoNotOptimize(grpc_slice_from_static_string("abc")); + } +} +BENCHMARK(BM_SliceFromStatic); + +static void BM_SliceFromCopied(benchmark::State& state) { + while (state.KeepRunning()) { + grpc_slice_unref(grpc_slice_from_copied_string("abc")); + } +} +BENCHMARK(BM_SliceFromCopied); + +static void BM_SliceIntern(benchmark::State& state) { + gpr_slice slice = grpc_slice_from_static_string("abc"); + while (state.KeepRunning()) { + grpc_slice_unref(grpc_slice_intern(slice)); + } +} +BENCHMARK(BM_SliceIntern); + +static void BM_SliceReIntern(benchmark::State& state) { + gpr_slice slice = grpc_slice_intern(grpc_slice_from_static_string("abc")); + while (state.KeepRunning()) { + grpc_slice_unref(grpc_slice_intern(slice)); + } + grpc_slice_unref(slice); +} +BENCHMARK(BM_SliceReIntern); + +static void BM_SliceInternStaticMetadata(benchmark::State& state) { + while (state.KeepRunning()) { + grpc_slice_intern(GRPC_MDSTR_GZIP); + } +} +BENCHMARK(BM_SliceInternStaticMetadata); + +static void BM_SliceInternEqualToStaticMetadata(benchmark::State& state) { + gpr_slice slice = grpc_slice_from_static_string("gzip"); + while (state.KeepRunning()) { + grpc_slice_intern(slice); + } +} +BENCHMARK(BM_SliceInternEqualToStaticMetadata); + +static void BM_MetadataFromNonInternedSlices(benchmark::State& state) { + gpr_slice k = grpc_slice_from_static_string("key"); + gpr_slice v = grpc_slice_from_static_string("value"); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL)); + } + grpc_exec_ctx_finish(&exec_ctx); +} +BENCHMARK(BM_MetadataFromNonInternedSlices); + +static void BM_MetadataFromInternedSlices(benchmark::State& state) { + gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key")); + gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value")); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL)); + } + grpc_exec_ctx_finish(&exec_ctx); + grpc_slice_unref(k); + grpc_slice_unref(v); +} +BENCHMARK(BM_MetadataFromInternedSlices); + +static void BM_MetadataFromInternedSlicesAlreadyInIndex( + benchmark::State& state) { + gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key")); + gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value")); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem seed = grpc_mdelem_create(&exec_ctx, k, v, NULL); + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL)); + } + GRPC_MDELEM_UNREF(&exec_ctx, seed); + grpc_exec_ctx_finish(&exec_ctx); + grpc_slice_unref(k); + grpc_slice_unref(v); +} +BENCHMARK(BM_MetadataFromInternedSlicesAlreadyInIndex); + +static void BM_MetadataFromInternedKey(benchmark::State& state) { + gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key")); + gpr_slice v = grpc_slice_from_static_string("value"); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL)); + } + grpc_exec_ctx_finish(&exec_ctx); + grpc_slice_unref(k); +} +BENCHMARK(BM_MetadataFromInternedKey); + +static void BM_MetadataFromNonInternedSlicesWithBackingStore( + benchmark::State& state) { + gpr_slice k = grpc_slice_from_static_string("key"); + gpr_slice v = grpc_slice_from_static_string("value"); + char backing_store[sizeof(grpc_mdelem_data)]; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF( + &exec_ctx, + grpc_mdelem_create(&exec_ctx, k, v, + reinterpret_cast<grpc_mdelem_data*>(backing_store))); + } + grpc_exec_ctx_finish(&exec_ctx); +} +BENCHMARK(BM_MetadataFromNonInternedSlicesWithBackingStore); + +static void BM_MetadataFromInternedSlicesWithBackingStore( + benchmark::State& state) { + gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key")); + gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value")); + char backing_store[sizeof(grpc_mdelem_data)]; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF( + &exec_ctx, + grpc_mdelem_create(&exec_ctx, k, v, + reinterpret_cast<grpc_mdelem_data*>(backing_store))); + } + grpc_exec_ctx_finish(&exec_ctx); + grpc_slice_unref(k); + grpc_slice_unref(v); +} +BENCHMARK(BM_MetadataFromInternedSlicesWithBackingStore); + +static void BM_MetadataFromInternedKeyWithBackingStore( + benchmark::State& state) { + gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key")); + gpr_slice v = grpc_slice_from_static_string("value"); + char backing_store[sizeof(grpc_mdelem_data)]; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF( + &exec_ctx, + grpc_mdelem_create(&exec_ctx, k, v, + reinterpret_cast<grpc_mdelem_data*>(backing_store))); + } + grpc_exec_ctx_finish(&exec_ctx); + grpc_slice_unref(k); +} +BENCHMARK(BM_MetadataFromInternedKeyWithBackingStore); + +static void BM_MetadataFromStaticMetadataStrings(benchmark::State& state) { + gpr_slice k = GRPC_MDSTR_STATUS; + gpr_slice v = GRPC_MDSTR_200; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL)); + } + grpc_exec_ctx_finish(&exec_ctx); + grpc_slice_unref(k); +} +BENCHMARK(BM_MetadataFromStaticMetadataStrings); + +static void BM_MetadataFromStaticMetadataStringsNotIndexed( + benchmark::State& state) { + gpr_slice k = GRPC_MDSTR_STATUS; + gpr_slice v = GRPC_MDSTR_GZIP; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL)); + } + grpc_exec_ctx_finish(&exec_ctx); + grpc_slice_unref(k); +} +BENCHMARK(BM_MetadataFromStaticMetadataStringsNotIndexed); + +static void BM_MetadataRefUnrefExternal(benchmark::State& state) { + char backing_store[sizeof(grpc_mdelem_data)]; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem el = + grpc_mdelem_create(&exec_ctx, grpc_slice_from_static_string("a"), + grpc_slice_from_static_string("b"), + reinterpret_cast<grpc_mdelem_data*>(backing_store)); + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el)); + } + GRPC_MDELEM_UNREF(&exec_ctx, el); + grpc_exec_ctx_finish(&exec_ctx); +} +BENCHMARK(BM_MetadataRefUnrefExternal); + +static void BM_MetadataRefUnrefInterned(benchmark::State& state) { + char backing_store[sizeof(grpc_mdelem_data)]; + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key")); + gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value")); + grpc_mdelem el = grpc_mdelem_create( + &exec_ctx, k, v, reinterpret_cast<grpc_mdelem_data*>(backing_store)); + grpc_slice_unref(k); + grpc_slice_unref(v); + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el)); + } + GRPC_MDELEM_UNREF(&exec_ctx, el); + grpc_exec_ctx_finish(&exec_ctx); +} +BENCHMARK(BM_MetadataRefUnrefInterned); + +static void BM_MetadataRefUnrefAllocated(benchmark::State& state) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem el = + grpc_mdelem_create(&exec_ctx, grpc_slice_from_static_string("a"), + grpc_slice_from_static_string("b"), NULL); + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el)); + } + GRPC_MDELEM_UNREF(&exec_ctx, el); + grpc_exec_ctx_finish(&exec_ctx); +} +BENCHMARK(BM_MetadataRefUnrefAllocated); + +static void BM_MetadataRefUnrefStatic(benchmark::State& state) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_mdelem el = + grpc_mdelem_create(&exec_ctx, GRPC_MDSTR_STATUS, GRPC_MDSTR_200, NULL); + while (state.KeepRunning()) { + GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el)); + } + GRPC_MDELEM_UNREF(&exec_ctx, el); + grpc_exec_ctx_finish(&exec_ctx); +} +BENCHMARK(BM_MetadataRefUnrefStatic); + +BENCHMARK_MAIN(); diff --git a/test/cpp/microbenchmarks/representative_server_initial_metadata.headers b/test/cpp/microbenchmarks/representative_server_initial_metadata.headers new file mode 100644 index 0000000000..d3e6933366 --- /dev/null +++ b/test/cpp/microbenchmarks/representative_server_initial_metadata.headers @@ -0,0 +1,4 @@ +:status: 200 +content-type: application/grpc +grpc-accept-encoding: identity,deflate,gzip + diff --git a/test/cpp/microbenchmarks/representative_server_trailing_metadata.headers b/test/cpp/microbenchmarks/representative_server_trailing_metadata.headers new file mode 100644 index 0000000000..544d089853 --- /dev/null +++ b/test/cpp/microbenchmarks/representative_server_trailing_metadata.headers @@ -0,0 +1,3 @@ +grpc-status: 0 +grpc-message: + |