Modify hpack benchmark scenarios (#27567)

It used to be that we could run the hpack deserializer into an arbitrary
sink - that's about to change and the hpack deserializer will buffer
directly into a map. That being the case, it's really hard to compare
performance of the current and the new system. With this PR, I'm
updating the relevant scenario to be more similar to the eventual
scenario that we plan, so that as the new work finishes up, we can get a
clearer idea of what changes we're really making.
pull/27586/head
Craig Tiller 3 years ago committed by GitHub
parent 60a5e474b8
commit b2942f601c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 226
      test/cpp/microbenchmarks/bm_chttp2_hpack.cc

@ -434,12 +434,60 @@ static void BM_HpackParserInitDestroy(benchmark::State& state) {
}
BENCHMARK(BM_HpackParserInitDestroy);
static grpc_error_handle UnrefHeader(void* /*user_data*/, grpc_mdelem md) {
GRPC_MDELEM_UNREF(md);
static void free_timeout(void* p) { gpr_free(p); }
// Benchmark the current on_initial_header implementation
static grpc_error_handle 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(
static_cast<grpc_core::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_handle error =
grpc_chttp2_incoming_metadata_buffer_add(&buffer, md);
if (error != GRPC_ERROR_NONE) {
GPR_ASSERT(0);
}
}
return GRPC_ERROR_NONE;
}
template <class Fixture, grpc_error_handle (*OnHeader)(void*, grpc_mdelem)>
template <class Fixture>
static void BM_HpackParserParseHeader(benchmark::State& state) {
TrackCounters track_counters;
grpc_core::ExecCtx exec_ctx;
@ -448,7 +496,7 @@ static void BM_HpackParserParseHeader(benchmark::State& state) {
grpc_core::HPackParser p;
const int kArenaSize = 4096 * 4096;
auto* arena = grpc_core::Arena::Create(kArenaSize);
p.BeginFrame([arena](grpc_mdelem e) { return OnHeader(arena, e); },
p.BeginFrame([arena](grpc_mdelem e) { return OnInitialHeader(arena, e); },
grpc_core::HPackParser::Boundary::None,
grpc_core::HPackParser::Priority::None);
for (auto slice : init_slices) {
@ -463,7 +511,7 @@ static void BM_HpackParserParseHeader(benchmark::State& state) {
if (0 == (state.iterations() & 0xfff)) {
arena->Destroy();
arena = grpc_core::Arena::Create(kArenaSize);
p.BeginFrame([arena](grpc_mdelem e) { return OnHeader(arena, e); },
p.BeginFrame([arena](grpc_mdelem e) { return OnInitialHeader(arena, e); },
grpc_core::HPackParser::Boundary::None,
grpc_core::HPackParser::Priority::None);
}
@ -702,14 +750,13 @@ class MoreRepresentativeClientInitialMetadata {
'x', ')'})};
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice(
{0xc7, 0xc6, 0xc5, 0xc4, 0x7f, 0x04, 0x31, 0x00, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x7f, 0x03, 0x14, 0x00,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0xc1, 0xc0, 0xbf, 0xbe})};
return {MakeSlice({
0xc7, 0xc6, 0xc5, 0xc4, 0x7f, 0x04, 0x31, 0x00, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
})};
}
};
@ -766,91 +813,6 @@ class RepresentativeServerTrailingMetadata {
}
};
static void free_timeout(void* p) { gpr_free(p); }
// Benchmark the current on_initial_header implementation
static grpc_error_handle 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(
static_cast<grpc_core::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_handle error =
grpc_chttp2_incoming_metadata_buffer_add(&buffer, md);
if (error != GRPC_ERROR_NONE) {
GPR_ASSERT(0);
}
}
return GRPC_ERROR_NONE;
}
// Benchmark timeout handling
static grpc_error_handle 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));
grpc_millis timeout;
if (cached_timeout != nullptr) {
timeout = *cached_timeout;
} else {
if (!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 {
GPR_ASSERT(0);
}
return GRPC_ERROR_NONE;
}
// Send the same deadline repeatedly
class SameDeadline {
public:
@ -865,55 +827,39 @@ class SameDeadline {
}
};
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, EmptyBatch, UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleStaticElem,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleStaticElem,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleStaticElem,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleInternedElem,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleInternedElem,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleInternedElem,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedElem, UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, false>,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, false>,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, false>,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, false>,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, false>,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, true>,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, true>,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, true>,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, true>,
UnrefHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, true>,
UnrefHeader);
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, NonIndexedBinaryElem<1, false>);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, false>);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, false>);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, false>);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, false>);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, true>);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, true>);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, true>);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, true>);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, true>);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
RepresentativeClientInitialMetadata, UnrefHeader);
RepresentativeClientInitialMetadata);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
MoreRepresentativeClientInitialMetadata, UnrefHeader);
MoreRepresentativeClientInitialMetadata);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
RepresentativeServerInitialMetadata, UnrefHeader);
RepresentativeServerInitialMetadata);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
RepresentativeServerTrailingMetadata, UnrefHeader);
RepresentativeServerTrailingMetadata);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
RepresentativeClientInitialMetadata, OnInitialHeader);
RepresentativeClientInitialMetadata);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
MoreRepresentativeClientInitialMetadata, OnInitialHeader);
MoreRepresentativeClientInitialMetadata);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
RepresentativeServerInitialMetadata, OnInitialHeader);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, SameDeadline, OnHeaderTimeout);
RepresentativeServerInitialMetadata);
BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, SameDeadline);
} // namespace hpack_parser_fixtures

Loading…
Cancel
Save