|
|
|
@ -27,6 +27,7 @@ |
|
|
|
|
|
|
|
|
|
#include "src/core/ext/transport/chttp2/transport/hpack_encoder.h" |
|
|
|
|
#include "src/core/ext/transport/chttp2/transport/hpack_parser.h" |
|
|
|
|
#include "src/core/ext/transport/chttp2/transport/incoming_metadata.h" |
|
|
|
|
#include "src/core/lib/slice/slice_internal.h" |
|
|
|
|
#include "src/core/lib/slice/slice_string_helpers.h" |
|
|
|
|
#include "src/core/lib/transport/static_metadata.h" |
|
|
|
@ -456,8 +457,9 @@ static void BM_HpackParserParseHeader(benchmark::State& state) { |
|
|
|
|
std::vector<grpc_slice> benchmark_slices = Fixture::GetBenchmarkSlices(); |
|
|
|
|
grpc_chttp2_hpack_parser p; |
|
|
|
|
grpc_chttp2_hpack_parser_init(&p); |
|
|
|
|
const int kArenaSize = 4096 * 4096; |
|
|
|
|
p.on_header_user_data = gpr_arena_create(kArenaSize); |
|
|
|
|
p.on_header = OnHeader; |
|
|
|
|
p.on_header_user_data = nullptr; |
|
|
|
|
for (auto slice : init_slices) { |
|
|
|
|
GPR_ASSERT(GRPC_ERROR_NONE == grpc_chttp2_hpack_parser_parse(&p, slice)); |
|
|
|
|
} |
|
|
|
@ -466,7 +468,14 @@ static void BM_HpackParserParseHeader(benchmark::State& state) { |
|
|
|
|
GPR_ASSERT(GRPC_ERROR_NONE == grpc_chttp2_hpack_parser_parse(&p, slice)); |
|
|
|
|
} |
|
|
|
|
grpc_core::ExecCtx::Get()->Flush(); |
|
|
|
|
// Recreate arena every 4k iterations to avoid oom
|
|
|
|
|
if (0 == (state.iterations() & 0xfff)) { |
|
|
|
|
gpr_arena_destroy((gpr_arena*)p.on_header_user_data); |
|
|
|
|
p.on_header_user_data = gpr_arena_create(kArenaSize); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Clean up
|
|
|
|
|
gpr_arena_destroy((gpr_arena*)p.on_header_user_data); |
|
|
|
|
for (auto slice : init_slices) grpc_slice_unref(slice); |
|
|
|
|
for (auto slice : benchmark_slices) grpc_slice_unref(slice); |
|
|
|
|
grpc_chttp2_hpack_parser_destroy(&p); |
|
|
|
@ -766,8 +775,58 @@ class RepresentativeServerTrailingMetadata { |
|
|
|
|
|
|
|
|
|
static void free_timeout(void* p) { gpr_free(p); } |
|
|
|
|
|
|
|
|
|
// New implementation.
|
|
|
|
|
static void OnHeaderNew(void* user_data, grpc_mdelem md) { |
|
|
|
|
// Benchmark the current on_initial_header implementation
|
|
|
|
|
static void OnInitialHeader(void* user_data, grpc_mdelem md) { |
|
|
|
|
// Setup for benchmark. This will bloat the absolute values of this benchmark
|
|
|
|
|
grpc_chttp2_incoming_metadata_buffer buffer; |
|
|
|
|
grpc_chttp2_incoming_metadata_buffer_init(&buffer, (gpr_arena*)user_data); |
|
|
|
|
bool seen_error = false; |
|
|
|
|
|
|
|
|
|
// Below here is the code we actually care about benchmarking
|
|
|
|
|
if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS) && |
|
|
|
|
!grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) { |
|
|
|
|
seen_error = true; |
|
|
|
|
} |
|
|
|
|
if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) { |
|
|
|
|
grpc_millis* cached_timeout = |
|
|
|
|
static_cast<grpc_millis*>(grpc_mdelem_get_user_data(md, free_timeout)); |
|
|
|
|
grpc_millis timeout; |
|
|
|
|
if (cached_timeout != nullptr) { |
|
|
|
|
timeout = *cached_timeout; |
|
|
|
|
} else { |
|
|
|
|
if (GPR_UNLIKELY( |
|
|
|
|
!grpc_http2_decode_timeout(GRPC_MDVALUE(md), &timeout))) { |
|
|
|
|
char* val = grpc_slice_to_c_string(GRPC_MDVALUE(md)); |
|
|
|
|
gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val); |
|
|
|
|
gpr_free(val); |
|
|
|
|
timeout = GRPC_MILLIS_INF_FUTURE; |
|
|
|
|
} |
|
|
|
|
if (GRPC_MDELEM_IS_INTERNED(md)) { |
|
|
|
|
/* not already parsed: parse it now, and store the
|
|
|
|
|
* result away */ |
|
|
|
|
cached_timeout = |
|
|
|
|
static_cast<grpc_millis*>(gpr_malloc(sizeof(grpc_millis))); |
|
|
|
|
*cached_timeout = timeout; |
|
|
|
|
grpc_mdelem_set_user_data(md, free_timeout, cached_timeout); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
benchmark::DoNotOptimize(timeout); |
|
|
|
|
GRPC_MDELEM_UNREF(md); |
|
|
|
|
} else { |
|
|
|
|
const size_t new_size = buffer.size + GRPC_MDELEM_LENGTH(md); |
|
|
|
|
if (!seen_error) { |
|
|
|
|
buffer.size = new_size; |
|
|
|
|
} |
|
|
|
|
grpc_error* error = grpc_chttp2_incoming_metadata_buffer_add(&buffer, md); |
|
|
|
|
if (error != GRPC_ERROR_NONE) { |
|
|
|
|
GPR_ASSERT(0); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
grpc_chttp2_incoming_metadata_buffer_destroy(&buffer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Benchmark timeout handling
|
|
|
|
|
static void OnHeaderTimeout(void* user_data, grpc_mdelem md) { |
|
|
|
|
if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) { |
|
|
|
|
grpc_millis* cached_timeout = |
|
|
|
|
static_cast<grpc_millis*>(grpc_mdelem_get_user_data(md, free_timeout)); |
|
|
|
@ -853,8 +912,13 @@ BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, |
|
|
|
|
RepresentativeServerInitialMetadata, UnrefHeader); |
|
|
|
|
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, |
|
|
|
|
RepresentativeServerTrailingMetadata, UnrefHeader); |
|
|
|
|
|
|
|
|
|
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, SameDeadline, OnHeaderNew); |
|
|
|
|
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, |
|
|
|
|
RepresentativeClientInitialMetadata, OnInitialHeader); |
|
|
|
|
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, |
|
|
|
|
MoreRepresentativeClientInitialMetadata, OnInitialHeader); |
|
|
|
|
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, |
|
|
|
|
RepresentativeServerInitialMetadata, OnInitialHeader); |
|
|
|
|
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, SameDeadline, OnHeaderTimeout); |
|
|
|
|
|
|
|
|
|
} // namespace hpack_parser_fixtures
|
|
|
|
|
|
|
|
|
|