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 3 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;
} // namespace
void HPackParser::FinishFrame() {
sink_ = Sink();
dynamic_table_updates_allowed_ = 2;
}
void GPR_ATTRIBUTE_NOINLINE HPackParser::LogHeader(grpc_mdelem md) {
char* k = grpc_slice_to_c_string(GRPC_MDKEY(md));
char* v = nullptr;
@ -1538,6 +1533,18 @@ HPackParser::HPackParser() {
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) {
sink_ = std::move(sink);
boundary_ = boundary;
@ -1551,16 +1558,36 @@ void HPackParser::BeginFrame(Sink sink, Boundary boundary, Priority priority) {
}
}
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);
void HPackParser::QueueBufferToParse(const grpc_slice& slice) {
queued_slices_.push_back(grpc_slice_ref_internal(slice));
}
grpc_error_handle HPackParser::Parse(const grpc_slice& last_slice) {
grpc_error_handle error = GRPC_ERROR_NONE;
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
* compilers without TCO */
#define MAX_PARSE_LENGTH 1024
@ -1628,48 +1655,42 @@ grpc_error_handle grpc_chttp2_header_parser_parse(void* hpack_parser,
if (s != nullptr) {
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);
if (error != GRPC_ERROR_NONE) {
return error;
}
if (is_last) {
if (parser->is_boundary() && !parser->is_in_begin_state()) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"end of header frame not aligned with a hpack record boundary");
/* need to check for null stream: this can occur if we receive an invalid
stream id on a header */
if (s != nullptr) {
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
stream id on a header */
if (s != nullptr) {
if (parser->is_boundary()) {
if (s->header_frames_received == GPR_ARRAY_SIZE(s->metadata_buffer)) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Too many trailer frames");
}
/* Process stream compression md element if it exists */
if (s->header_frames_received ==
0) { /* Only acts on initial metadata */
parse_stream_compression_md(t, s, &s->metadata_buffer[0].batch);
}
s->published_metadata[s->header_frames_received] =
GRPC_METADATA_PUBLISHED_FROM_WIRE;
maybe_complete_funcs[s->header_frames_received](t, s);
s->header_frames_received++;
}
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);
/* Process stream compression md element if it exists */
if (s->header_frames_received == 0) { /* Only acts on initial metadata */
parse_stream_compression_md(t, s, &s->metadata_buffer[0].batch);
}
s->published_metadata[s->header_frames_received] =
GRPC_METADATA_PUBLISHED_FROM_WIRE;
maybe_complete_funcs[s->header_frames_received](t, s);
s->header_frames_received++;
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);
}
parser->FinishFrame();
}
parser->FinishFrame();
return GRPC_ERROR_NONE;
}

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

@ -320,9 +320,8 @@ grpc_error_handle skip_header(grpc_mdelem md) {
return GRPC_ERROR_NONE;
}
static HPackParser::Boundary hpack_boundary_type(grpc_chttp2_transport* t,
bool is_eoh) {
if (is_eoh) {
static HPackParser::Boundary hpack_boundary_type(grpc_chttp2_transport* t) {
if ((t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0) {
if (t->header_eof) {
return HPackParser::Boundary::EndOfStream;
} else {
@ -335,10 +334,9 @@ static HPackParser::Boundary hpack_boundary_type(grpc_chttp2_transport* t,
static grpc_error_handle init_header_skip_frame_parser(
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_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);
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");
return init_header_skip_frame_parser(t, priority_type);
}
t->hpack_parser.BeginFrame(std::move(on_header),
hpack_boundary_type(t, is_eoh), priority_type);
t->hpack_parser.BeginFrame(std::move(on_header), hpack_boundary_type(t),
priority_type);
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,
GPR_DUMP_HEX | GPR_DUMP_ASCII);
/* 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);
} else {
gpr_log(GPR_INFO, "TEST: (%" PRIdPTR " byte long string)",
arg->client_payload_length);
gpr_log(GPR_INFO, "TEST[line=%d]: (%" PRIdPTR " byte long string)",
arg->source_line, arg->client_payload_length);
}
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"
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};
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);
struct grpc_bad_client_arg {
int source_line;
grpc_bad_client_client_stream_validator client_validator;
void* client_validator_arg;
const char* client_payload;
@ -68,10 +69,10 @@ void grpc_run_bad_client_test(
#define COMBINE1(X, Y) X##Y
#define COMBINE(X, Y) COMBINE1(X, Y)
#define GRPC_RUN_BAD_CLIENT_TEST(server_validator, client_validator, payload, \
flags) \
grpc_bad_client_arg COMBINE(bca, __LINE__) = {client_validator, nullptr, \
payload, sizeof(payload) - 1}; \
#define GRPC_RUN_BAD_CLIENT_TEST(server_validator, client_validator, payload, \
flags) \
grpc_bad_client_arg COMBINE(bca, __LINE__) = { \
__LINE__, client_validator, nullptr, payload, sizeof(payload) - 1}; \
grpc_run_bad_client_test(server_validator, &COMBINE(bca, __LINE__), 1, flags)
/* Helper validator functions */

@ -91,7 +91,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq,
nullptr);
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
CQ_EXPECT_COMPLETION_ANY_STATUS(cqv, tag(102));
cq_verify(cqv);
memset(ops, 0, sizeof(ops));
@ -113,7 +113,7 @@ static void verifier(grpc_server* server, grpc_completion_queue* cq,
nullptr);
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_call_details_destroy(&call_details);

@ -131,7 +131,7 @@ int main(int argc, char** argv) {
addbuf(hdr, sizeof(hdr));
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);
gpr_free(g_buffer);
grpc_shutdown();

@ -38,7 +38,7 @@
#define PFX_TOO_MUCH_METADATA_FROM_CLIENT_REQUEST \
"\x00\x00\x00\x04\x01\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\x07:scheme\x04http" \
"\x10\x07:method\x04POST" \

@ -94,7 +94,7 @@ int main(int argc, char** argv) {
}
grpc_bad_client_arg bca[2];
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);
gpr_free(g_buffer);
grpc_shutdown();

@ -63,9 +63,14 @@ static void test_vector(grpc_core::HPackParser* parser,
grpc_split_slices(mode, &input, 1, &slices, &nslices);
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;
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++) {

@ -452,35 +452,40 @@ template <class Fixture, grpc_error_handle (*OnHeader)(void*, grpc_mdelem)>
static void BM_HpackParserParseHeader(benchmark::State& state) {
TrackCounters track_counters;
grpc_core::ExecCtx exec_ctx;
std::vector<grpc_slice> init_slices = Fixture::GetInitSlices();
std::vector<grpc_slice> benchmark_slices = Fixture::GetBenchmarkSlices();
absl::optional<grpc_slice> init_slice = Fixture::GetInitSlice();
grpc_slice benchmark_slice = Fixture::GetBenchmarkSlice();
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); },
grpc_core::HPackParser::Boundary::None,
grpc_core::HPackParser::Boundary::EndOfHeaders,
grpc_core::HPackParser::Priority::None);
for (auto slice : init_slices) {
GPR_ASSERT(GRPC_ERROR_NONE == p.Parse(slice));
}
while (state.KeepRunning()) {
for (auto slice : benchmark_slices) {
GPR_ASSERT(GRPC_ERROR_NONE == p.Parse(slice));
auto check_error = [](grpc_error_handle e) {
if (e != GRPC_ERROR_NONE) {
gpr_log(GPR_ERROR, "%s", grpc_error_string(e));
abort();
}
};
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();
// Recreate arena every 4k iterations to avoid oom
if (0 == (state.iterations() & 0xfff)) {
arena->Destroy();
arena = grpc_core::Arena::Create(kArenaSize);
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);
}
}
// Clean up
arena->Destroy();
for (auto slice : init_slices) grpc_slice_unref(slice);
for (auto slice : benchmark_slices) grpc_slice_unref(slice);
if (init_slice.has_value()) grpc_slice_unref(*init_slice);
grpc_slice_unref(benchmark_slice);
track_counters.Finish(state);
}
@ -489,76 +494,70 @@ namespace hpack_parser_fixtures {
class EmptyBatch {
public:
static std::vector<grpc_slice> GetInitSlices() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice({})};
}
static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static grpc_slice GetBenchmarkSlice() { 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})};
static absl::optional<grpc_slice> GetInitSlice() {
return MakeSlice(
{0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'});
}
static grpc_slice GetBenchmarkSlice() { 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'})};
static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static grpc_slice GetBenchmarkSlice() {
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 absl::optional<grpc_slice> GetInitSlice() {
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'})};
static grpc_slice GetBenchmarkSlice() {
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})};
static absl::optional<grpc_slice> GetInitSlice() {
return MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'});
}
static grpc_slice GetBenchmarkSlice() { 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'})};
static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static grpc_slice GetBenchmarkSlice() {
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 absl::optional<grpc_slice> GetInitSlice() {
return MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'});
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice({0x7e, 0x03, 'g', 'h', 'i'})};
static grpc_slice GetBenchmarkSlice() {
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'})};
static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static grpc_slice GetBenchmarkSlice() {
return MakeSlice({0x00, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'});
}
};
@ -568,8 +567,8 @@ class NonIndexedBinaryElem;
template <int kLength>
class NonIndexedBinaryElem<kLength, true> {
public:
static std::vector<grpc_slice> GetInitSlices() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() {
static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static grpc_slice GetBenchmarkSlice() {
std::vector<uint8_t> v = {
0x00, 0x07, 'a', 'b', 'c',
'-', 'b', 'i', 'n', static_cast<uint8_t>(kLength + 1),
@ -577,60 +576,60 @@ class NonIndexedBinaryElem<kLength, true> {
for (int i = 0; i < kLength; i++) {
v.push_back(static_cast<uint8_t>(i));
}
return {MakeSlice(v)};
return MakeSlice(v);
}
};
template <>
class NonIndexedBinaryElem<1, false> {
public:
static std::vector<grpc_slice> GetInitSlices() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice(
{0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x82, 0xf7, 0xb3})};
static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static grpc_slice GetBenchmarkSlice() {
return MakeSlice(
{0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x82, 0xf7, 0xb3});
}
};
template <>
class NonIndexedBinaryElem<3, false> {
public:
static std::vector<grpc_slice> GetInitSlices() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x84,
0x7f, 0x4e, 0x29, 0x3f})};
static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static grpc_slice GetBenchmarkSlice() {
return MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x84, 0x7f,
0x4e, 0x29, 0x3f});
}
};
template <>
class NonIndexedBinaryElem<10, false> {
public:
static std::vector<grpc_slice> GetInitSlices() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b',
'i', 'n', 0x8b, 0x71, 0x0c, 0xa5, 0x81,
0x73, 0x7b, 0x47, 0x13, 0xe9, 0xf7, 0xe3})};
static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static grpc_slice GetBenchmarkSlice() {
return MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b',
'i', 'n', 0x8b, 0x71, 0x0c, 0xa5, 0x81,
0x73, 0x7b, 0x47, 0x13, 0xe9, 0xf7, 0xe3});
}
};
template <>
class NonIndexedBinaryElem<31, false> {
public:
static std::vector<grpc_slice> GetInitSlices() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n',
0xa3, 0x92, 0x43, 0x7f, 0xbe, 0x7c, 0xea, 0x6f, 0xf3,
0x3d, 0xa7, 0xa7, 0x67, 0xfb, 0xe2, 0x82, 0xf7, 0xf2,
0x8f, 0x1f, 0x9d, 0xdf, 0xf1, 0x7e, 0xb3, 0xef, 0xb2,
0x8f, 0x53, 0x77, 0xce, 0x0c, 0x13, 0xe3, 0xfd, 0x87})};
static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static grpc_slice GetBenchmarkSlice() {
return MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n',
0xa3, 0x92, 0x43, 0x7f, 0xbe, 0x7c, 0xea, 0x6f, 0xf3,
0x3d, 0xa7, 0xa7, 0x67, 0xfb, 0xe2, 0x82, 0xf7, 0xf2,
0x8f, 0x1f, 0x9d, 0xdf, 0xf1, 0x7e, 0xb3, 0xef, 0xb2,
0x8f, 0x53, 0x77, 0xce, 0x0c, 0x13, 0xe3, 0xfd, 0x87});
}
};
template <>
class NonIndexedBinaryElem<100, false> {
public:
static std::vector<grpc_slice> GetInitSlices() { return {}; }
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice(
static absl::optional<grpc_slice> GetInitSlice() { return {}; }
static grpc_slice GetBenchmarkSlice() {
return MakeSlice(
{0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0xeb, 0x1d, 0x4d,
0xe8, 0x96, 0x8c, 0x14, 0x20, 0x06, 0xc1, 0xc3, 0xdf, 0x6e, 0x1f, 0xef,
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,
0x01, 0x89, 0x13, 0xd7, 0xca, 0x17, 0x6e, 0xcb, 0xd6, 0x79, 0x71, 0x68,
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 {
public:
static std::vector<grpc_slice> GetInitSlices() {
static absl::optional<grpc_slice> GetInitSlice() {
return {grpc_slice_from_static_string(
// generated with:
// ```
@ -664,13 +663,13 @@ class RepresentativeClientInitialMetadata {
"@\x02te\x08trailers"
"@\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)")};
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
static grpc_slice GetBenchmarkSlice() {
// 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})};
return MakeSlice({0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf, 0xbe});
}
};
@ -679,8 +678,8 @@ class RepresentativeClientInitialMetadata {
// the corresponding encoder benchmark above.
class MoreRepresentativeClientInitialMetadata {
public:
static std::vector<grpc_slice> GetInitSlices() {
return {MakeSlice(
static absl::optional<grpc_slice> GetInitSlice() {
return MakeSlice(
{0x40, 0x07, ':', 's', 'c', 'h', 'e', 'm', 'e', 0x04, 'h', 't',
't', 'p', 0x40, 0x07, ':', 'm', 'e', 't', 'h', 'o', 'd', 0x04,
'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',
'n', 't', ' ', 'g', 'r', 'p', 'c', '-', 'c', '/', '0', '.',
'1', '2', '.', '0', '.', '0', ' ', '(', 'l', 'i', 'n', 'u',
'x', ')'})};
'x', ')'});
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
return {MakeSlice(
static grpc_slice GetBenchmarkSlice() {
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})};
0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0xc1, 0xc0, 0xbf, 0xbe});
}
};
class RepresentativeServerInitialMetadata {
public:
static std::vector<grpc_slice> GetInitSlices() {
static absl::optional<grpc_slice> GetInitSlice() {
return {grpc_slice_from_static_string(
// generated with:
// ```
@ -739,39 +738,40 @@ class RepresentativeServerInitialMetadata {
"application/grpc"
"@\x14grpc-accept-encoding\x15identity,deflate,gzip")};
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
static grpc_slice GetBenchmarkSlice() {
// 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})};
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 absl::optional<grpc_slice> GetInitSlice() {
// generated with:
// ```
// tools/codegen/core/gen_header_frame.py --compression inc --no_framing
// --hex
// <
// test/cpp/microbenchmarks/representative_server_trailing_metadata.headers
// ```
return MakeSlice({0x40, 0x0b, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x73,
0x74, 0x61, 0x74, 0x75, 0x73, 0x01, 0x30, 0x40,
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:
// ```
// tools/codegen/core/gen_header_frame.py --compression pre --no_framing
// --hex <
// 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
class SameDeadline {
public:
static std::vector<grpc_slice> GetInitSlices() {
static absl::optional<grpc_slice> GetInitSlice() {
return {
grpc_slice_from_static_string("@\x0cgrpc-timeout\x03"
"30S")};
}
static std::vector<grpc_slice> GetBenchmarkSlices() {
static grpc_slice GetBenchmarkSlice() {
// 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