Buffer HPACK parsing until the end of a header boundary (#26700)

HTTP2 headers are sent in (potentially) many frames, but all must be
sent sequentially with no traffic intervening.

This was not clear when I wrote the HPACK parser, and still indeed quite
contentious on the HTTP2 mailing lists.

Now that matter is well settled (years ago!) take advantage of the fact
by delaying parsing until all bytes are available.

A future change will leverage this to avoid having to store and verify
partial parse state, completely eliminating indirect calls within the
parser.
pull/26822/head
Craig Tiller 4 years ago committed by GitHub
parent db9fa2eaa0
commit 8bab3e4bf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 117
      src/core/ext/transport/chttp2/transport/hpack_parser.cc
  2. 8
      src/core/ext/transport/chttp2/transport/hpack_parser.h
  3. 12
      src/core/ext/transport/chttp2/transport/parsing.cc
  4. 8
      test/core/bad_client/bad_client.cc
  5. 9
      test/core/bad_client/bad_client.h
  6. 4
      test/core/bad_client/tests/duplicate_header.cc
  7. 2
      test/core/bad_client/tests/head_of_line_blocking.cc
  8. 2
      test/core/bad_client/tests/large_metadata.cc
  9. 2
      test/core/bad_client/tests/window_overflow.cc
  10. 9
      test/core/transport/chttp2/hpack_parser_test.cc
  11. 202
      test/cpp/microbenchmarks/bm_chttp2_hpack.cc

@ -464,11 +464,6 @@ struct Base64InverseTable {
static GRPC_HPACK_CONSTEXPR_VALUE Base64InverseTable kBase64InverseTable; static GRPC_HPACK_CONSTEXPR_VALUE Base64InverseTable kBase64InverseTable;
} // namespace } // namespace
void HPackParser::FinishFrame() {
sink_ = Sink();
dynamic_table_updates_allowed_ = 2;
}
void GPR_ATTRIBUTE_NOINLINE HPackParser::LogHeader(grpc_mdelem md) { void GPR_ATTRIBUTE_NOINLINE HPackParser::LogHeader(grpc_mdelem md) {
char* k = grpc_slice_to_c_string(GRPC_MDKEY(md)); char* k = grpc_slice_to_c_string(GRPC_MDKEY(md));
char* v = nullptr; char* v = nullptr;
@ -1538,6 +1533,18 @@ HPackParser::HPackParser() {
last_error_ = GRPC_ERROR_NONE; last_error_ = GRPC_ERROR_NONE;
} }
HPackParser::~HPackParser() {
grpc_chttp2_hptbl_destroy(&table_);
GRPC_ERROR_UNREF(last_error_);
grpc_slice_unref_internal(key_.data_.referenced);
grpc_slice_unref_internal(value_.data_.referenced);
gpr_free(key_.data_.copied.str);
gpr_free(value_.data_.copied.str);
for (const auto& slice : queued_slices_) {
grpc_slice_unref_internal(slice);
}
}
void HPackParser::BeginFrame(Sink sink, Boundary boundary, Priority priority) { void HPackParser::BeginFrame(Sink sink, Boundary boundary, Priority priority) {
sink_ = std::move(sink); sink_ = std::move(sink);
boundary_ = boundary; boundary_ = boundary;
@ -1551,16 +1558,36 @@ void HPackParser::BeginFrame(Sink sink, Boundary boundary, Priority priority) {
} }
} }
HPackParser::~HPackParser() { void HPackParser::QueueBufferToParse(const grpc_slice& slice) {
grpc_chttp2_hptbl_destroy(&table_); queued_slices_.push_back(grpc_slice_ref_internal(slice));
GRPC_ERROR_UNREF(last_error_); }
grpc_slice_unref_internal(key_.data_.referenced);
grpc_slice_unref_internal(value_.data_.referenced); grpc_error_handle HPackParser::Parse(const grpc_slice& last_slice) {
gpr_free(key_.data_.copied.str); grpc_error_handle error = GRPC_ERROR_NONE;
gpr_free(value_.data_.copied.str); for (const auto& slice : queued_slices_) {
error = ParseOneSlice(slice);
if (error != GRPC_ERROR_NONE) break;
}
for (const auto& slice : queued_slices_) {
grpc_slice_unref_internal(slice);
}
queued_slices_.clear();
if (error == GRPC_ERROR_NONE) {
error = ParseOneSlice(last_slice);
}
if (error == GRPC_ERROR_NONE && state_ != &HPackParser::parse_begin) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"end of header frame not aligned with a hpack record boundary");
}
return error;
} }
grpc_error_handle HPackParser::Parse(const grpc_slice& slice) { void HPackParser::FinishFrame() {
sink_ = Sink();
dynamic_table_updates_allowed_ = 2;
}
grpc_error_handle HPackParser::ParseOneSlice(const grpc_slice& slice) {
/* max number of bytes to parse at a time... limits call stack depth on /* max number of bytes to parse at a time... limits call stack depth on
* compilers without TCO */ * compilers without TCO */
#define MAX_PARSE_LENGTH 1024 #define MAX_PARSE_LENGTH 1024
@ -1628,48 +1655,42 @@ grpc_error_handle grpc_chttp2_header_parser_parse(void* hpack_parser,
if (s != nullptr) { if (s != nullptr) {
s->stats.incoming.header_bytes += GRPC_SLICE_LENGTH(slice); s->stats.incoming.header_bytes += GRPC_SLICE_LENGTH(slice);
} }
if (!is_last || !parser->is_boundary()) {
parser->QueueBufferToParse(slice);
return GRPC_ERROR_NONE;
}
grpc_error_handle error = parser->Parse(slice); grpc_error_handle error = parser->Parse(slice);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
return error; return error;
} }
if (is_last) { /* need to check for null stream: this can occur if we receive an invalid
if (parser->is_boundary() && !parser->is_in_begin_state()) { stream id on a header */
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( if (s != nullptr) {
"end of header frame not aligned with a hpack record boundary"); if (s->header_frames_received == GPR_ARRAY_SIZE(s->metadata_buffer)) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Too many trailer frames");
} }
/* need to check for null stream: this can occur if we receive an invalid /* Process stream compression md element if it exists */
stream id on a header */ if (s->header_frames_received == 0) { /* Only acts on initial metadata */
if (s != nullptr) { parse_stream_compression_md(t, s, &s->metadata_buffer[0].batch);
if (parser->is_boundary()) { }
if (s->header_frames_received == GPR_ARRAY_SIZE(s->metadata_buffer)) { s->published_metadata[s->header_frames_received] =
return GRPC_ERROR_CREATE_FROM_STATIC_STRING( GRPC_METADATA_PUBLISHED_FROM_WIRE;
"Too many trailer frames"); maybe_complete_funcs[s->header_frames_received](t, s);
} s->header_frames_received++;
/* Process stream compression md element if it exists */ if (parser->is_eof()) {
if (s->header_frames_received == if (t->is_client && !s->write_closed) {
0) { /* Only acts on initial metadata */ /* server eof ==> complete closure; we may need to forcefully close
parse_stream_compression_md(t, s, &s->metadata_buffer[0].batch); the stream. Wait until the combiner lock is ready to be released
} however -- it might be that we receive a RST_STREAM following this
s->published_metadata[s->header_frames_received] = and can avoid the extra write */
GRPC_METADATA_PUBLISHED_FROM_WIRE; GRPC_CHTTP2_STREAM_REF(s, "final_rst");
maybe_complete_funcs[s->header_frames_received](t, s); t->combiner->FinallyRun(
s->header_frames_received++; GRPC_CLOSURE_CREATE(force_client_rst_stream, s, nullptr),
} GRPC_ERROR_NONE);
if (parser->is_eof()) {
if (t->is_client && !s->write_closed) {
/* server eof ==> complete closure; we may need to forcefully close
the stream. Wait until the combiner lock is ready to be released
however -- it might be that we receive a RST_STREAM following this
and can avoid the extra write */
GRPC_CHTTP2_STREAM_REF(s, "final_rst");
t->combiner->FinallyRun(
GRPC_CLOSURE_CREATE(force_client_rst_stream, s, nullptr),
GRPC_ERROR_NONE);
}
grpc_chttp2_mark_stream_closed(t, s, true, false, GRPC_ERROR_NONE);
} }
grpc_chttp2_mark_stream_closed(t, s, true, false, GRPC_ERROR_NONE);
} }
parser->FinishFrame();
} }
parser->FinishFrame();
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }

@ -45,13 +45,13 @@ class HPackParser {
void BeginFrame(Sink sink, Boundary boundary, Priority priority); void BeginFrame(Sink sink, Boundary boundary, Priority priority);
void ResetSink(Sink sink) { sink_ = std::move(sink); } void ResetSink(Sink sink) { sink_ = std::move(sink); }
grpc_error_handle Parse(const grpc_slice& slice); void QueueBufferToParse(const grpc_slice& slice);
grpc_error_handle Parse(const grpc_slice& last_slice);
void FinishFrame(); void FinishFrame();
grpc_chttp2_hptbl* hpack_table() { return &table_; } grpc_chttp2_hptbl* hpack_table() { return &table_; }
bool is_boundary() const { return boundary_ != Boundary::None; } bool is_boundary() const { return boundary_ != Boundary::None; }
bool is_eof() const { return boundary_ == Boundary::EndOfStream; } bool is_eof() const { return boundary_ == Boundary::EndOfStream; }
bool is_in_begin_state() const { return state_ == &HPackParser::parse_begin; }
private: private:
enum class BinaryState { enum class BinaryState {
@ -175,9 +175,13 @@ class HPackParser {
grpc_error_handle AppendHuffBytes(const uint8_t* cur, const uint8_t* end); grpc_error_handle AppendHuffBytes(const uint8_t* cur, const uint8_t* end);
grpc_error_handle AppendStrBytes(const uint8_t* cur, const uint8_t* end); grpc_error_handle AppendStrBytes(const uint8_t* cur, const uint8_t* end);
grpc_error_handle ParseOneSlice(const grpc_slice& slice);
Sink sink_; Sink sink_;
grpc_error_handle last_error_; grpc_error_handle last_error_;
absl::InlinedVector<grpc_slice, 2> queued_slices_;
// current parse state - or a function that implements it // current parse state - or a function that implements it
State state_; State state_;
// future states dependent on the opening op code // future states dependent on the opening op code

@ -320,9 +320,8 @@ grpc_error_handle skip_header(grpc_mdelem md) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
static HPackParser::Boundary hpack_boundary_type(grpc_chttp2_transport* t, static HPackParser::Boundary hpack_boundary_type(grpc_chttp2_transport* t) {
bool is_eoh) { if ((t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0) {
if (is_eoh) {
if (t->header_eof) { if (t->header_eof) {
return HPackParser::Boundary::EndOfStream; return HPackParser::Boundary::EndOfStream;
} else { } else {
@ -335,10 +334,9 @@ static HPackParser::Boundary hpack_boundary_type(grpc_chttp2_transport* t,
static grpc_error_handle init_header_skip_frame_parser( static grpc_error_handle init_header_skip_frame_parser(
grpc_chttp2_transport* t, HPackParser::Priority priority_type) { grpc_chttp2_transport* t, HPackParser::Priority priority_type) {
bool is_eoh = t->expect_continuation_stream_id != 0;
t->parser = grpc_chttp2_header_parser_parse; t->parser = grpc_chttp2_header_parser_parse;
t->parser_data = &t->hpack_parser; t->parser_data = &t->hpack_parser;
t->hpack_parser.BeginFrame(skip_header, hpack_boundary_type(t, is_eoh), t->hpack_parser.BeginFrame(skip_header, hpack_boundary_type(t),
priority_type); priority_type);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
@ -695,8 +693,8 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
gpr_log(GPR_ERROR, "too many header frames received"); gpr_log(GPR_ERROR, "too many header frames received");
return init_header_skip_frame_parser(t, priority_type); return init_header_skip_frame_parser(t, priority_type);
} }
t->hpack_parser.BeginFrame(std::move(on_header), t->hpack_parser.BeginFrame(std::move(on_header), hpack_boundary_type(t),
hpack_boundary_type(t, is_eoh), priority_type); priority_type);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }

@ -96,11 +96,11 @@ void grpc_run_client_side_validator(grpc_bad_client_arg* arg, uint32_t flags,
hex = gpr_dump(arg->client_payload, arg->client_payload_length, hex = gpr_dump(arg->client_payload, arg->client_payload_length,
GPR_DUMP_HEX | GPR_DUMP_ASCII); GPR_DUMP_HEX | GPR_DUMP_ASCII);
/* Add a debug log */ /* Add a debug log */
gpr_log(GPR_INFO, "TEST: %s", hex); gpr_log(GPR_INFO, "TEST[line=%d]: %s", arg->source_line, hex);
gpr_free(hex); gpr_free(hex);
} else { } else {
gpr_log(GPR_INFO, "TEST: (%" PRIdPTR " byte long string)", gpr_log(GPR_INFO, "TEST[line=%d]: (%" PRIdPTR " byte long string)",
arg->client_payload_length); arg->source_line, arg->client_payload_length);
} }
grpc_slice slice = grpc_slice_from_copied_buffer(arg->client_payload, grpc_slice slice = grpc_slice_from_copied_buffer(arg->client_payload,
@ -272,7 +272,7 @@ bool client_connection_preface_validator(grpc_slice_buffer* incoming,
"\x00\x00\x00\x04\x00\x00\x00\x00\x00" "\x00\x00\x00\x04\x00\x00\x00\x00\x00"
grpc_bad_client_arg connection_preface_arg = { grpc_bad_client_arg connection_preface_arg = {
client_connection_preface_validator, nullptr, -1, client_connection_preface_validator, nullptr,
CONNECTION_PREFACE_FROM_CLIENT, sizeof(CONNECTION_PREFACE_FROM_CLIENT) - 1}; CONNECTION_PREFACE_FROM_CLIENT, sizeof(CONNECTION_PREFACE_FROM_CLIENT) - 1};
bool rst_stream_client_validator(grpc_slice_buffer* incoming, void* /*arg*/) { bool rst_stream_client_validator(grpc_slice_buffer* incoming, void* /*arg*/) {

@ -38,6 +38,7 @@ typedef bool (*grpc_bad_client_client_stream_validator)(
grpc_slice_buffer* incoming, void* arg); grpc_slice_buffer* incoming, void* arg);
struct grpc_bad_client_arg { struct grpc_bad_client_arg {
int source_line;
grpc_bad_client_client_stream_validator client_validator; grpc_bad_client_client_stream_validator client_validator;
void* client_validator_arg; void* client_validator_arg;
const char* client_payload; const char* client_payload;
@ -68,10 +69,10 @@ void grpc_run_bad_client_test(
#define COMBINE1(X, Y) X##Y #define COMBINE1(X, Y) X##Y
#define COMBINE(X, Y) COMBINE1(X, Y) #define COMBINE(X, Y) COMBINE1(X, Y)
#define GRPC_RUN_BAD_CLIENT_TEST(server_validator, client_validator, payload, \ #define GRPC_RUN_BAD_CLIENT_TEST(server_validator, client_validator, payload, \
flags) \ flags) \
grpc_bad_client_arg COMBINE(bca, __LINE__) = {client_validator, nullptr, \ grpc_bad_client_arg COMBINE(bca, __LINE__) = { \
payload, sizeof(payload) - 1}; \ __LINE__, client_validator, nullptr, payload, sizeof(payload) - 1}; \
grpc_run_bad_client_test(server_validator, &COMBINE(bca, __LINE__), 1, flags) grpc_run_bad_client_test(server_validator, &COMBINE(bca, __LINE__), 1, flags)
/* Helper validator functions */ /* Helper validator functions */

@ -91,7 +91,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq,
nullptr); nullptr);
GPR_ASSERT(GRPC_CALL_OK == error); GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(102), 1); CQ_EXPECT_COMPLETION_ANY_STATUS(cqv, tag(102));
cq_verify(cqv); cq_verify(cqv);
memset(ops, 0, sizeof(ops)); memset(ops, 0, sizeof(ops));
@ -113,7 +113,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq,
nullptr); nullptr);
GPR_ASSERT(GRPC_CALL_OK == error); GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(103), 1); CQ_EXPECT_COMPLETION_ANY_STATUS(cqv, tag(103));
grpc_metadata_array_destroy(&request_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details); grpc_call_details_destroy(&call_details);

@ -131,7 +131,7 @@ int main(int argc, char** argv) {
addbuf(hdr, sizeof(hdr)); addbuf(hdr, sizeof(hdr));
addbuf(msg, FRAME_SIZE); addbuf(msg, FRAME_SIZE);
} }
grpc_bad_client_arg bca = {nullptr, nullptr, g_buffer, g_count}; grpc_bad_client_arg bca = {__LINE__, nullptr, nullptr, g_buffer, g_count};
grpc_run_bad_client_test(verifier, &bca, 1, 0); grpc_run_bad_client_test(verifier, &bca, 1, 0);
gpr_free(g_buffer); gpr_free(g_buffer);
grpc_shutdown(); grpc_shutdown();

@ -38,7 +38,7 @@
#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_REQUEST \ #define PFX_TOO_MUCH_METADATA_FROM_CLIENT_REQUEST \
"\x00\x00\x00\x04\x01\x00\x00\x00\x00" \ "\x00\x00\x00\x04\x01\x00\x00\x00\x00" \
"\x00" \ "\x00" \
"5{\x01\x05\x00\x00\x00\x01" \ "\x1aM\x01\x05\x00\x00\x00\x01" \
"\x10\x05:path\x08/foo/bar" \ "\x10\x05:path\x08/foo/bar" \
"\x10\x07:scheme\x04http" \ "\x10\x07:scheme\x04http" \
"\x10\x07:method\x04POST" \ "\x10\x07:method\x04POST" \

@ -94,7 +94,7 @@ int main(int argc, char** argv) {
} }
grpc_bad_client_arg bca[2]; grpc_bad_client_arg bca[2];
bca[0] = connection_preface_arg; bca[0] = connection_preface_arg;
bca[1] = {rst_stream_client_validator, nullptr, g_buffer, g_count}; bca[1] = {__LINE__, rst_stream_client_validator, nullptr, g_buffer, g_count};
grpc_run_bad_client_test(verifier, bca, 2, GRPC_BAD_CLIENT_LARGE_REQUEST); grpc_run_bad_client_test(verifier, bca, 2, GRPC_BAD_CLIENT_LARGE_REQUEST);
gpr_free(g_buffer); gpr_free(g_buffer);
grpc_shutdown(); grpc_shutdown();

@ -63,9 +63,14 @@ static void test_vector(grpc_core::HPackParser* parser,
grpc_split_slices(mode, &input, 1, &slices, &nslices); grpc_split_slices(mode, &input, 1, &slices, &nslices);
grpc_slice_unref(input); grpc_slice_unref(input);
for (i = 0; i < nslices; i++) { GPR_ASSERT(nslices > 0);
for (i = 0; i < nslices - 1; i++) {
parser->QueueBufferToParse(slices[i]);
}
{
grpc_core::ExecCtx exec_ctx; grpc_core::ExecCtx exec_ctx;
GPR_ASSERT(parser->Parse(slices[i]) == GRPC_ERROR_NONE); GPR_ASSERT(parser->Parse(slices[nslices - 1]) == GRPC_ERROR_NONE);
} }
for (i = 0; i < nslices; i++) { for (i = 0; i < nslices; i++) {

@ -452,35 +452,40 @@ template <class Fixture, grpc_error_handle (*OnHeader)(void*, grpc_mdelem)>
static void BM_HpackParserParseHeader(benchmark::State& state) { static void BM_HpackParserParseHeader(benchmark::State& state) {
TrackCounters track_counters; TrackCounters track_counters;
grpc_core::ExecCtx exec_ctx; grpc_core::ExecCtx exec_ctx;
std::vector<grpc_slice> init_slices = Fixture::GetInitSlices(); absl::optional<grpc_slice> init_slice = Fixture::GetInitSlice();
std::vector<grpc_slice> benchmark_slices = Fixture::GetBenchmarkSlices(); grpc_slice benchmark_slice = Fixture::GetBenchmarkSlice();
grpc_core::HPackParser p; grpc_core::HPackParser p;
const int kArenaSize = 4096 * 4096; const int kArenaSize = 4096 * 4096;
auto* arena = grpc_core::Arena::Create(kArenaSize); auto* arena = grpc_core::Arena::Create(kArenaSize);
p.BeginFrame([arena](grpc_mdelem e) { return OnHeader(arena, e); }, p.BeginFrame([arena](grpc_mdelem e) { return OnHeader(arena, e); },
grpc_core::HPackParser::Boundary::None, grpc_core::HPackParser::Boundary::EndOfHeaders,
grpc_core::HPackParser::Priority::None); grpc_core::HPackParser::Priority::None);
for (auto slice : init_slices) { auto check_error = [](grpc_error_handle e) {
GPR_ASSERT(GRPC_ERROR_NONE == p.Parse(slice)); if (e != GRPC_ERROR_NONE) {
} gpr_log(GPR_ERROR, "%s", grpc_error_string(e));
while (state.KeepRunning()) { abort();
for (auto slice : benchmark_slices) {
GPR_ASSERT(GRPC_ERROR_NONE == p.Parse(slice));
} }
};
if (init_slice.has_value()) check_error(p.Parse(*init_slice));
p.FinishFrame();
while (state.KeepRunning()) {
p.ResetSink([arena](grpc_mdelem e) { return OnHeader(arena, e); });
check_error(p.Parse(benchmark_slice));
p.FinishFrame();
grpc_core::ExecCtx::Get()->Flush(); grpc_core::ExecCtx::Get()->Flush();
// Recreate arena every 4k iterations to avoid oom // Recreate arena every 4k iterations to avoid oom
if (0 == (state.iterations() & 0xfff)) { if (0 == (state.iterations() & 0xfff)) {
arena->Destroy(); arena->Destroy();
arena = grpc_core::Arena::Create(kArenaSize); arena = grpc_core::Arena::Create(kArenaSize);
p.BeginFrame([arena](grpc_mdelem e) { return OnHeader(arena, e); }, p.BeginFrame([arena](grpc_mdelem e) { return OnHeader(arena, e); },
grpc_core::HPackParser::Boundary::None, grpc_core::HPackParser::Boundary::EndOfHeaders,
grpc_core::HPackParser::Priority::None); grpc_core::HPackParser::Priority::None);
} }
} }
// Clean up // Clean up
arena->Destroy(); arena->Destroy();
for (auto slice : init_slices) grpc_slice_unref(slice); if (init_slice.has_value()) grpc_slice_unref(*init_slice);
for (auto slice : benchmark_slices) grpc_slice_unref(slice); grpc_slice_unref(benchmark_slice);
track_counters.Finish(state); track_counters.Finish(state);
} }
@ -489,76 +494,70 @@ namespace hpack_parser_fixtures {
class EmptyBatch { class EmptyBatch {
public: public:
static std::vector<grpc_slice> GetInitSlices() { return {}; } static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() { return MakeSlice({}); }
return {MakeSlice({})};
}
}; };
class IndexedSingleStaticElem { class IndexedSingleStaticElem {
public: public:
static std::vector<grpc_slice> GetInitSlices() { static absl::optional<grpc_slice> GetInitSlice() {
return {MakeSlice( return MakeSlice(
{0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})}; {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'});
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice({0xbe})};
} }
static grpc_slice GetBenchmarkSlice() { return MakeSlice({0xbe}); }
}; };
class AddIndexedSingleStaticElem { class AddIndexedSingleStaticElem {
public: public:
static std::vector<grpc_slice> GetInitSlices() { return {}; } static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
return {MakeSlice( return MakeSlice(
{0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})}; {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'});
} }
}; };
class KeyIndexedSingleStaticElem { class KeyIndexedSingleStaticElem {
public: public:
static std::vector<grpc_slice> GetInitSlices() { static absl::optional<grpc_slice> GetInitSlice() {
return {MakeSlice( return MakeSlice(
{0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})}; {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'});
} }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
return {MakeSlice({0x7e, 0x03, 'd', 'e', 'f'})}; return MakeSlice({0x7e, 0x03, 'd', 'e', 'f'});
} }
}; };
class IndexedSingleInternedElem { class IndexedSingleInternedElem {
public: public:
static std::vector<grpc_slice> GetInitSlices() { static absl::optional<grpc_slice> GetInitSlice() {
return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})}; return MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'});
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice({0xbe})};
} }
static grpc_slice GetBenchmarkSlice() { return MakeSlice({0xbe}); }
}; };
class AddIndexedSingleInternedElem { class AddIndexedSingleInternedElem {
public: public:
static std::vector<grpc_slice> GetInitSlices() { return {}; } static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})}; return MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'});
} }
}; };
class KeyIndexedSingleInternedElem { class KeyIndexedSingleInternedElem {
public: public:
static std::vector<grpc_slice> GetInitSlices() { static absl::optional<grpc_slice> GetInitSlice() {
return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})}; return MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'});
} }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
return {MakeSlice({0x7e, 0x03, 'g', 'h', 'i'})}; return MakeSlice({0x7e, 0x03, 'g', 'h', 'i'});
} }
}; };
class NonIndexedElem { class NonIndexedElem {
public: public:
static std::vector<grpc_slice> GetInitSlices() { return {}; } static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
return {MakeSlice({0x00, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})}; return MakeSlice({0x00, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'});
} }
}; };
@ -568,8 +567,8 @@ class NonIndexedBinaryElem;
template <int kLength> template <int kLength>
class NonIndexedBinaryElem<kLength, true> { class NonIndexedBinaryElem<kLength, true> {
public: public:
static std::vector<grpc_slice> GetInitSlices() { return {}; } static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
std::vector<uint8_t> v = { std::vector<uint8_t> v = {
0x00, 0x07, 'a', 'b', 'c', 0x00, 0x07, 'a', 'b', 'c',
'-', 'b', 'i', 'n', static_cast<uint8_t>(kLength + 1), '-', 'b', 'i', 'n', static_cast<uint8_t>(kLength + 1),
@ -577,60 +576,60 @@ class NonIndexedBinaryElem<kLength, true> {
for (int i = 0; i < kLength; i++) { for (int i = 0; i < kLength; i++) {
v.push_back(static_cast<uint8_t>(i)); v.push_back(static_cast<uint8_t>(i));
} }
return {MakeSlice(v)}; return MakeSlice(v);
} }
}; };
template <> template <>
class NonIndexedBinaryElem<1, false> { class NonIndexedBinaryElem<1, false> {
public: public:
static std::vector<grpc_slice> GetInitSlices() { return {}; } static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
return {MakeSlice( return MakeSlice(
{0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x82, 0xf7, 0xb3})}; {0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x82, 0xf7, 0xb3});
} }
}; };
template <> template <>
class NonIndexedBinaryElem<3, false> { class NonIndexedBinaryElem<3, false> {
public: public:
static std::vector<grpc_slice> GetInitSlices() { return {}; } static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
return {MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x84, return MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x84, 0x7f,
0x7f, 0x4e, 0x29, 0x3f})}; 0x4e, 0x29, 0x3f});
} }
}; };
template <> template <>
class NonIndexedBinaryElem<10, false> { class NonIndexedBinaryElem<10, false> {
public: public:
static std::vector<grpc_slice> GetInitSlices() { return {}; } static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
return {MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', return MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b',
'i', 'n', 0x8b, 0x71, 0x0c, 0xa5, 0x81, 'i', 'n', 0x8b, 0x71, 0x0c, 0xa5, 0x81,
0x73, 0x7b, 0x47, 0x13, 0xe9, 0xf7, 0xe3})}; 0x73, 0x7b, 0x47, 0x13, 0xe9, 0xf7, 0xe3});
} }
}; };
template <> template <>
class NonIndexedBinaryElem<31, false> { class NonIndexedBinaryElem<31, false> {
public: public:
static std::vector<grpc_slice> GetInitSlices() { return {}; } static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
return {MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', return MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n',
0xa3, 0x92, 0x43, 0x7f, 0xbe, 0x7c, 0xea, 0x6f, 0xf3, 0xa3, 0x92, 0x43, 0x7f, 0xbe, 0x7c, 0xea, 0x6f, 0xf3,
0x3d, 0xa7, 0xa7, 0x67, 0xfb, 0xe2, 0x82, 0xf7, 0xf2, 0x3d, 0xa7, 0xa7, 0x67, 0xfb, 0xe2, 0x82, 0xf7, 0xf2,
0x8f, 0x1f, 0x9d, 0xdf, 0xf1, 0x7e, 0xb3, 0xef, 0xb2, 0x8f, 0x1f, 0x9d, 0xdf, 0xf1, 0x7e, 0xb3, 0xef, 0xb2,
0x8f, 0x53, 0x77, 0xce, 0x0c, 0x13, 0xe3, 0xfd, 0x87})}; 0x8f, 0x53, 0x77, 0xce, 0x0c, 0x13, 0xe3, 0xfd, 0x87});
} }
}; };
template <> template <>
class NonIndexedBinaryElem<100, false> { class NonIndexedBinaryElem<100, false> {
public: public:
static std::vector<grpc_slice> GetInitSlices() { return {}; } static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
return {MakeSlice( return MakeSlice(
{0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0xeb, 0x1d, 0x4d, {0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0xeb, 0x1d, 0x4d,
0xe8, 0x96, 0x8c, 0x14, 0x20, 0x06, 0xc1, 0xc3, 0xdf, 0x6e, 0x1f, 0xef, 0xe8, 0x96, 0x8c, 0x14, 0x20, 0x06, 0xc1, 0xc3, 0xdf, 0x6e, 0x1f, 0xef,
0xde, 0x2f, 0xde, 0xb7, 0xf2, 0xfe, 0x6d, 0xd4, 0xe4, 0x7d, 0xf5, 0x55, 0xde, 0x2f, 0xde, 0xb7, 0xf2, 0xfe, 0x6d, 0xd4, 0xe4, 0x7d, 0xf5, 0x55,
@ -640,13 +639,13 @@ class NonIndexedBinaryElem<100, false> {
0x78, 0x6b, 0xdb, 0xa5, 0xb7, 0xab, 0xe7, 0x46, 0xae, 0x21, 0xab, 0x7f, 0x78, 0x6b, 0xdb, 0xa5, 0xb7, 0xab, 0xe7, 0x46, 0xae, 0x21, 0xab, 0x7f,
0x01, 0x89, 0x13, 0xd7, 0xca, 0x17, 0x6e, 0xcb, 0xd6, 0x79, 0x71, 0x68, 0x01, 0x89, 0x13, 0xd7, 0xca, 0x17, 0x6e, 0xcb, 0xd6, 0x79, 0x71, 0x68,
0xbf, 0x8a, 0x3f, 0x32, 0xe8, 0xba, 0xf5, 0xbe, 0xb3, 0xbc, 0xde, 0x28, 0xbf, 0x8a, 0x3f, 0x32, 0xe8, 0xba, 0xf5, 0xbe, 0xb3, 0xbc, 0xde, 0x28,
0xc7, 0xcf, 0x62, 0x7a, 0x58, 0x2c, 0xcf, 0x4d, 0xe3})}; 0xc7, 0xcf, 0x62, 0x7a, 0x58, 0x2c, 0xcf, 0x4d, 0xe3});
} }
}; };
class RepresentativeClientInitialMetadata { class RepresentativeClientInitialMetadata {
public: public:
static std::vector<grpc_slice> GetInitSlices() { static absl::optional<grpc_slice> GetInitSlice() {
return {grpc_slice_from_static_string( return {grpc_slice_from_static_string(
// generated with: // generated with:
// ``` // ```
@ -664,13 +663,13 @@ class RepresentativeClientInitialMetadata {
"@\x02te\x08trailers" "@\x02te\x08trailers"
"@\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)")}; "@\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)")};
} }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
// generated with: // generated with:
// ``` // ```
// tools/codegen/core/gen_header_frame.py --compression pre --no_framing // tools/codegen/core/gen_header_frame.py --compression pre --no_framing
// --hex < test/core/bad_client/tests/simple_request.headers // --hex < test/core/bad_client/tests/simple_request.headers
// ``` // ```
return {MakeSlice({0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe})}; return MakeSlice({0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe});
} }
}; };
@ -679,8 +678,8 @@ class RepresentativeClientInitialMetadata {
// the corresponding encoder benchmark above. // the corresponding encoder benchmark above.
class MoreRepresentativeClientInitialMetadata { class MoreRepresentativeClientInitialMetadata {
public: public:
static std::vector<grpc_slice> GetInitSlices() { static absl::optional<grpc_slice> GetInitSlice() {
return {MakeSlice( return MakeSlice(
{0x40, 0x07, ':', 's', 'c', 'h', 'e', 'm', 'e', 0x04, 'h', 't', {0x40, 0x07, ':', 's', 'c', 'h', 'e', 'm', 'e', 0x04, 'h', 't',
't', 'p', 0x40, 0x07, ':', 'm', 'e', 't', 'h', 'o', 'd', 0x04, 't', 'p', 0x40, 0x07, ':', 'm', 'e', 't', 'h', 'o', 'd', 0x04,
'P', 'O', 'S', 'T', 0x40, 0x05, ':', 'p', 'a', 't', 'h', 0x1f, 'P', 'O', 'S', 'T', 0x40, 0x05, ':', 'p', 'a', 't', 'h', 0x1f,
@ -708,23 +707,23 @@ class MoreRepresentativeClientInitialMetadata {
'e', 'n', 't', 0x22, 'b', 'a', 'd', '-', 'c', 'l', 'i', 'e', 'e', 'n', 't', 0x22, 'b', 'a', 'd', '-', 'c', 'l', 'i', 'e',
'n', 't', ' ', 'g', 'r', 'p', 'c', '-', 'c', '/', '0', '.', 'n', 't', ' ', 'g', 'r', 'p', 'c', '-', 'c', '/', '0', '.',
'1', '2', '.', '0', '.', '0', ' ', '(', 'l', 'i', 'n', 'u', '1', '2', '.', '0', '.', '0', ' ', '(', 'l', 'i', 'n', 'u',
'x', ')'})}; 'x', ')'});
} }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
return {MakeSlice( return MakeSlice(
{0xc7, 0xc6, 0xc5, 0xc4, 0x7f, 0x04, 0x31, 0x00, 0x01, 0x02, 0x03, 0x04, {0xc7, 0xc6, 0xc5, 0xc4, 0x7f, 0x04, 0x31, 0x00, 0x01, 0x02, 0x03, 0x04,
0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x7f, 0x03, 0x14, 0x00, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x7f, 0x03, 0x14, 0x00,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0xc1, 0xc0, 0xbf, 0xbe})}; 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0xc1, 0xc0, 0xbf, 0xbe});
} }
}; };
class RepresentativeServerInitialMetadata { class RepresentativeServerInitialMetadata {
public: public:
static std::vector<grpc_slice> GetInitSlices() { static absl::optional<grpc_slice> GetInitSlice() {
return {grpc_slice_from_static_string( return {grpc_slice_from_static_string(
// generated with: // generated with:
// ``` // ```
@ -739,39 +738,40 @@ class RepresentativeServerInitialMetadata {
"application/grpc" "application/grpc"
"@\x14grpc-accept-encoding\x15identity,deflate,gzip")}; "@\x14grpc-accept-encoding\x15identity,deflate,gzip")};
} }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
// generated with: // generated with:
// ``` // ```
// tools/codegen/core/gen_header_frame.py --compression pre --no_framing // tools/codegen/core/gen_header_frame.py --compression pre --no_framing
// --hex < // --hex <
// test/cpp/microbenchmarks/representative_server_initial_metadata.headers // test/cpp/microbenchmarks/representative_server_initial_metadata.headers
// ``` // ```
return {MakeSlice({0xc0, 0xbf, 0xbe})}; return MakeSlice({0xc0, 0xbf, 0xbe});
} }
}; };
class RepresentativeServerTrailingMetadata { class RepresentativeServerTrailingMetadata {
public: public:
static std::vector<grpc_slice> GetInitSlices() { static absl::optional<grpc_slice> GetInitSlice() {
return {grpc_slice_from_static_string( // generated with:
// generated with: // ```
// ``` // tools/codegen/core/gen_header_frame.py --compression inc --no_framing
// tools/codegen/core/gen_header_frame.py --compression inc --no_framing // --hex
// < // <
// test/cpp/microbenchmarks/representative_server_trailing_metadata.headers // test/cpp/microbenchmarks/representative_server_trailing_metadata.headers
// ``` // ```
"@\x0bgrpc-status\x01" return MakeSlice({0x40, 0x0b, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x73,
"0" 0x74, 0x61, 0x74, 0x75, 0x73, 0x01, 0x30, 0x40,
"@\x0cgrpc-message\x00")}; 0x0c, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x6d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x00});
} }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
// generated with: // generated with:
// ``` // ```
// tools/codegen/core/gen_header_frame.py --compression pre --no_framing // tools/codegen/core/gen_header_frame.py --compression pre --no_framing
// --hex < // --hex <
// test/cpp/microbenchmarks/representative_server_trailing_metadata.headers // test/cpp/microbenchmarks/representative_server_trailing_metadata.headers
// ``` // ```
return {MakeSlice({0xbf, 0xbe})}; return MakeSlice({0xbf, 0xbe});
} }
}; };
@ -863,14 +863,14 @@ static grpc_error_handle OnHeaderTimeout(void* /*user_data*/, grpc_mdelem md) {
// Send the same deadline repeatedly // Send the same deadline repeatedly
class SameDeadline { class SameDeadline {
public: public:
static std::vector<grpc_slice> GetInitSlices() { static absl::optional<grpc_slice> GetInitSlice() {
return { return {
grpc_slice_from_static_string("@\x0cgrpc-timeout\x03" grpc_slice_from_static_string("@\x0cgrpc-timeout\x03"
"30S")}; "30S")};
} }
static std::vector<grpc_slice> GetBenchmarkSlices() { static grpc_slice GetBenchmarkSlice() {
// Use saved key and literal value. // Use saved key and literal value.
return {MakeSlice({0x0f, 0x2f, 0x03, '3', '0', 'S'})}; return MakeSlice({0x0f, 0x2f, 0x03, '3', '0', 'S'});
} }
}; };

Loading…
Cancel
Save