xref: /aosp_15_r20/external/grpc-grpc/test/cpp/microbenchmarks/bm_chttp2_hpack.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 // Microbenchmarks around CHTTP2 HPACK operations
20 
21 #include <string.h>
22 
23 #include <memory>
24 #include <sstream>
25 
26 #include <benchmark/benchmark.h>
27 
28 #include "absl/random/random.h"
29 
30 #include <grpc/slice.h>
31 #include <grpc/support/alloc.h>
32 #include <grpc/support/log.h>
33 
34 #include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
35 #include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
36 #include "src/core/lib/gprpp/crash.h"
37 #include "src/core/lib/gprpp/time.h"
38 #include "src/core/lib/resource_quota/resource_quota.h"
39 #include "src/core/lib/slice/slice_internal.h"
40 #include "src/core/lib/slice/slice_string_helpers.h"
41 #include "src/core/lib/transport/metadata_batch.h"
42 #include "src/core/lib/transport/timeout_encoding.h"
43 #include "test/core/util/test_config.h"
44 #include "test/cpp/microbenchmarks/helpers.h"
45 #include "test/cpp/util/test_config.h"
46 
MakeSlice(const std::vector<uint8_t> & bytes)47 static grpc_slice MakeSlice(const std::vector<uint8_t>& bytes) {
48   grpc_slice s = grpc_slice_malloc(bytes.size());
49   uint8_t* p = GRPC_SLICE_START_PTR(s);
50   for (auto b : bytes) {
51     *p++ = b;
52   }
53   return s;
54 }
55 
56 ////////////////////////////////////////////////////////////////////////////////
57 // HPACK encoder
58 //
59 
BM_HpackEncoderInitDestroy(benchmark::State & state)60 static void BM_HpackEncoderInitDestroy(benchmark::State& state) {
61   grpc_core::ExecCtx exec_ctx;
62   for (auto _ : state) {
63     grpc_core::HPackCompressor c;
64     grpc_core::ExecCtx::Get()->Flush();
65   }
66 }
67 BENCHMARK(BM_HpackEncoderInitDestroy);
68 
BM_HpackEncoderEncodeDeadline(benchmark::State & state)69 static void BM_HpackEncoderEncodeDeadline(benchmark::State& state) {
70   grpc_core::ExecCtx exec_ctx;
71   grpc_core::Timestamp saved_now = grpc_core::Timestamp::Now();
72 
73   grpc_core::MemoryAllocator memory_allocator =
74       grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
75                                      ->memory_quota()
76                                      ->CreateMemoryAllocator("test"));
77   auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
78   grpc_metadata_batch b;
79   b.Set(grpc_core::GrpcTimeoutMetadata(),
80         saved_now + grpc_core::Duration::Seconds(30));
81 
82   grpc_core::HPackCompressor c;
83   grpc_transport_one_way_stats stats;
84   stats = {};
85   grpc_slice_buffer outbuf;
86   grpc_slice_buffer_init(&outbuf);
87   while (state.KeepRunning()) {
88     c.EncodeHeaders(
89         grpc_core::HPackCompressor::EncodeHeaderOptions{
90             static_cast<uint32_t>(state.iterations()),
91             true,
92             false,
93             size_t{1024},
94             &stats,
95         },
96         b, &outbuf);
97     grpc_slice_buffer_reset_and_unref(&outbuf);
98     grpc_core::ExecCtx::Get()->Flush();
99   }
100   grpc_slice_buffer_destroy(&outbuf);
101 }
102 BENCHMARK(BM_HpackEncoderEncodeDeadline);
103 
104 template <class Fixture>
BM_HpackEncoderEncodeHeader(benchmark::State & state)105 static void BM_HpackEncoderEncodeHeader(benchmark::State& state) {
106   grpc_core::ExecCtx exec_ctx;
107   static bool logged_representative_output = false;
108 
109   grpc_core::MemoryAllocator memory_allocator =
110       grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
111                                      ->memory_quota()
112                                      ->CreateMemoryAllocator("test"));
113   auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
114   grpc_metadata_batch b;
115   Fixture::Prepare(&b);
116 
117   grpc_core::HPackCompressor c;
118   grpc_transport_one_way_stats stats;
119   stats = {};
120   grpc_slice_buffer outbuf;
121   grpc_slice_buffer_init(&outbuf);
122   while (state.KeepRunning()) {
123     static constexpr int kEnsureMaxFrameAtLeast = 2;
124     c.EncodeHeaders(
125         grpc_core::HPackCompressor::EncodeHeaderOptions{
126             static_cast<uint32_t>(state.iterations()),
127             state.range(0) != 0,
128             Fixture::kEnableTrueBinary,
129             static_cast<size_t>(state.range(1) + kEnsureMaxFrameAtLeast),
130             &stats,
131         },
132         b, &outbuf);
133     if (!logged_representative_output && state.iterations() > 3) {
134       logged_representative_output = true;
135       for (size_t i = 0; i < outbuf.count; i++) {
136         char* s = grpc_dump_slice(outbuf.slices[i], GPR_DUMP_HEX);
137         gpr_log(GPR_DEBUG, "%" PRIdPTR ": %s", i, s);
138         gpr_free(s);
139       }
140     }
141     grpc_slice_buffer_reset_and_unref(&outbuf);
142     grpc_core::ExecCtx::Get()->Flush();
143   }
144   grpc_slice_buffer_destroy(&outbuf);
145 }
146 
147 namespace hpack_encoder_fixtures {
148 
149 class EmptyBatch {
150  public:
151   static constexpr bool kEnableTrueBinary = false;
Prepare(grpc_metadata_batch *)152   static void Prepare(grpc_metadata_batch*) {}
153 };
154 
155 class SingleStaticElem {
156  public:
157   static constexpr bool kEnableTrueBinary = false;
Prepare(grpc_metadata_batch * b)158   static void Prepare(grpc_metadata_batch* b) {
159     b->Set(grpc_core::GrpcAcceptEncodingMetadata(),
160            grpc_core::CompressionAlgorithmSet(
161                {GRPC_COMPRESS_NONE, GRPC_COMPRESS_DEFLATE}));
162   }
163 };
164 
CrashOnAppendError(absl::string_view,const grpc_core::Slice &)165 static void CrashOnAppendError(absl::string_view, const grpc_core::Slice&) {
166   abort();
167 }
168 
169 class SingleNonBinaryElem {
170  public:
171   static constexpr bool kEnableTrueBinary = false;
Prepare(grpc_metadata_batch * b)172   static void Prepare(grpc_metadata_batch* b) {
173     b->Append("abc", grpc_core::Slice::FromStaticString("def"),
174               CrashOnAppendError);
175   }
176 };
177 
178 template <int kLength, bool kTrueBinary>
179 class SingleBinaryElem {
180  public:
181   static constexpr bool kEnableTrueBinary = kTrueBinary;
Prepare(grpc_metadata_batch * b)182   static void Prepare(grpc_metadata_batch* b) {
183     b->Append("abc-bin", MakeBytes(), CrashOnAppendError);
184   }
185 
186  private:
MakeBytes()187   static grpc_core::Slice MakeBytes() {
188     std::vector<char> v;
189     v.reserve(kLength);
190     for (int i = 0; i < kLength; i++) {
191       v.push_back(static_cast<char>(rand()));
192     }
193     return grpc_core::Slice::FromCopiedBuffer(v);
194   }
195 };
196 
197 class RepresentativeClientInitialMetadata {
198  public:
199   static constexpr bool kEnableTrueBinary = true;
Prepare(grpc_metadata_batch * b)200   static void Prepare(grpc_metadata_batch* b) {
201     b->Set(grpc_core::HttpSchemeMetadata(),
202            grpc_core::HttpSchemeMetadata::kHttp);
203     b->Set(grpc_core::HttpMethodMetadata(),
204            grpc_core::HttpMethodMetadata::kPost);
205     b->Set(
206         grpc_core::HttpPathMetadata(),
207         grpc_core::Slice(grpc_core::StaticSlice::FromStaticString("/foo/bar")));
208     b->Set(grpc_core::HttpAuthorityMetadata(),
209            grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
210                "foo.test.google.fr:1234")));
211     b->Set(
212         grpc_core::GrpcAcceptEncodingMetadata(),
213         grpc_core::CompressionAlgorithmSet(
214             {GRPC_COMPRESS_NONE, GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_GZIP}));
215     b->Set(grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers);
216     b->Set(grpc_core::ContentTypeMetadata(),
217            grpc_core::ContentTypeMetadata::kApplicationGrpc);
218     b->Set(grpc_core::UserAgentMetadata(),
219            grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
220                "grpc-c/3.0.0-dev (linux; chttp2; green)")));
221   }
222 };
223 
224 // This fixture reflects how initial metadata are sent by a production client,
225 // with non-indexed :path and binary headers. The metadata here are the same as
226 // the corresponding parser benchmark below.
227 class MoreRepresentativeClientInitialMetadata {
228  public:
229   static constexpr bool kEnableTrueBinary = true;
Prepare(grpc_metadata_batch * b)230   static void Prepare(grpc_metadata_batch* b) {
231     b->Set(grpc_core::HttpSchemeMetadata(),
232            grpc_core::HttpSchemeMetadata::kHttp);
233     b->Set(grpc_core::HttpMethodMetadata(),
234            grpc_core::HttpMethodMetadata::kPost);
235     b->Set(grpc_core::HttpPathMetadata(),
236            grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
237                "/grpc.test.FooService/BarMethod")));
238     b->Set(grpc_core::HttpAuthorityMetadata(),
239            grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
240                "foo.test.google.fr:1234")));
241     b->Set(grpc_core::GrpcTraceBinMetadata(),
242            grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
243                "\x00\x01\x02\x03\x04\x05\x06\x07\x08"
244                "\x09\x0a\x0b\x0c\x0d\x0e\x0f"
245                "\x10\x11\x12\x13\x14\x15\x16\x17\x18"
246                "\x19\x1a\x1b\x1c\x1d\x1e\x1f"
247                "\x20\x21\x22\x23\x24\x25\x26\x27\x28"
248                "\x29\x2a\x2b\x2c\x2d\x2e\x2f"
249                "\x30")));
250     b->Set(grpc_core::GrpcTagsBinMetadata(),
251            grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
252                "\x00\x01\x02\x03\x04\x05\x06\x07\x08"
253                "\x09\x0a\x0b\x0c\x0d\x0e\x0f"
254                "\x10\x11\x12\x13")));
255     b->Set(
256         grpc_core::GrpcAcceptEncodingMetadata(),
257         grpc_core::CompressionAlgorithmSet(
258             {GRPC_COMPRESS_NONE, GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_GZIP}));
259     b->Set(grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers);
260     b->Set(grpc_core::ContentTypeMetadata(),
261            grpc_core::ContentTypeMetadata::kApplicationGrpc);
262     b->Set(grpc_core::UserAgentMetadata(),
263            grpc_core::Slice(grpc_core::StaticSlice::FromStaticString(
264                "grpc-c/3.0.0-dev (linux; chttp2; green)")));
265   }
266 };
267 
268 class RepresentativeServerInitialMetadata {
269  public:
270   static constexpr bool kEnableTrueBinary = true;
Prepare(grpc_metadata_batch * b)271   static void Prepare(grpc_metadata_batch* b) {
272     b->Set(grpc_core::HttpStatusMetadata(), 200);
273     b->Set(grpc_core::ContentTypeMetadata(),
274            grpc_core::ContentTypeMetadata::kApplicationGrpc);
275     b->Set(
276         grpc_core::GrpcAcceptEncodingMetadata(),
277         grpc_core::CompressionAlgorithmSet(
278             {GRPC_COMPRESS_NONE, GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_GZIP}));
279   }
280 };
281 
282 class RepresentativeServerTrailingMetadata {
283  public:
284   static constexpr bool kEnableTrueBinary = true;
Prepare(grpc_metadata_batch * b)285   static void Prepare(grpc_metadata_batch* b) {
286     b->Set(grpc_core::GrpcStatusMetadata(), GRPC_STATUS_OK);
287   }
288 };
289 
290 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, EmptyBatch)->Args({0, 16384});
291 // test with eof (shouldn't affect anything)
292 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, EmptyBatch)->Args({1, 16384});
293 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleStaticElem)
294     ->Args({0, 16384});
295 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonBinaryElem)
296     ->Args({0, 16384});
297 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleBinaryElem<1, false>)
298     ->Args({0, 16384});
299 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleBinaryElem<3, false>)
300     ->Args({0, 16384});
301 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleBinaryElem<10, false>)
302     ->Args({0, 16384});
303 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleBinaryElem<31, false>)
304     ->Args({0, 16384});
305 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleBinaryElem<100, false>)
306     ->Args({0, 16384});
307 // test with a tiny frame size, to highlight continuation costs
308 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader, SingleNonBinaryElem)
309     ->Args({0, 1});
310 
311 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader,
312                    RepresentativeClientInitialMetadata)
313     ->Args({0, 16384});
314 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader,
315                    MoreRepresentativeClientInitialMetadata)
316     ->Args({0, 16384});
317 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader,
318                    RepresentativeServerInitialMetadata)
319     ->Args({0, 16384});
320 BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader,
321                    RepresentativeServerTrailingMetadata)
322     ->Args({1, 16384});
323 
324 }  // namespace hpack_encoder_fixtures
325 
326 ////////////////////////////////////////////////////////////////////////////////
327 // HPACK parser
328 //
329 
BM_HpackParserInitDestroy(benchmark::State & state)330 static void BM_HpackParserInitDestroy(benchmark::State& state) {
331   grpc_core::ExecCtx exec_ctx;
332   for (auto _ : state) {
333     {
334       grpc_core::HPackParser();
335     }
336     grpc_core::ExecCtx::Get()->Flush();
337   }
338 }
339 BENCHMARK(BM_HpackParserInitDestroy);
340 
341 template <class Fixture>
BM_HpackParserParseHeader(benchmark::State & state)342 static void BM_HpackParserParseHeader(benchmark::State& state) {
343   std::vector<grpc_slice> init_slices = Fixture::GetInitSlices();
344   std::vector<grpc_slice> benchmark_slices = Fixture::GetBenchmarkSlices();
345   grpc_core::ExecCtx exec_ctx;
346   grpc_core::HPackParser p;
347   const int kArenaSize = 4096 * 4096;
348   grpc_core::MemoryAllocator memory_allocator =
349       grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
350                                      ->memory_quota()
351                                      ->CreateMemoryAllocator("test"));
352   auto* arena = grpc_core::Arena::Create(kArenaSize, &memory_allocator);
353   grpc_core::ManualConstructor<grpc_metadata_batch> b;
354   b.Init();
355   p.BeginFrame(&*b, std::numeric_limits<uint32_t>::max(),
356                std::numeric_limits<uint32_t>::max(),
357                grpc_core::HPackParser::Boundary::None,
358                grpc_core::HPackParser::Priority::None,
359                grpc_core::HPackParser::LogInfo{
360                    1, grpc_core::HPackParser::LogInfo::kHeaders, false});
361   auto parse_vec = [&p, bitgen = absl::BitGen()](
362                        const std::vector<grpc_slice>& slices) mutable {
363     for (size_t i = 0; i < slices.size(); ++i) {
364       auto error =
365           p.Parse(slices[i], i == slices.size() - 1, absl::BitGenRef(bitgen),
366                   /*call_tracer=*/nullptr);
367       GPR_ASSERT(error.ok());
368     }
369   };
370   parse_vec(init_slices);
371   while (state.KeepRunning()) {
372     b->Clear();
373     parse_vec(benchmark_slices);
374     grpc_core::ExecCtx::Get()->Flush();
375     // Recreate arena every 4k iterations to avoid oom
376     if (0 == (state.iterations() & 0xfff)) {
377       b.Destroy();
378       arena->Destroy();
379       arena = grpc_core::Arena::Create(kArenaSize, &memory_allocator);
380       b.Init();
381       p.BeginFrame(&*b, std::numeric_limits<uint32_t>::max(),
382                    std::numeric_limits<uint32_t>::max(),
383                    grpc_core::HPackParser::Boundary::None,
384                    grpc_core::HPackParser::Priority::None,
385                    grpc_core::HPackParser::LogInfo{
386                        1, grpc_core::HPackParser::LogInfo::kHeaders, false});
387     }
388   }
389   // Clean up
390   b.Destroy();
391   for (auto slice : init_slices) grpc_slice_unref(slice);
392   for (auto slice : benchmark_slices) grpc_slice_unref(slice);
393   arena->Destroy();
394 }
395 
396 namespace hpack_parser_fixtures {
397 
398 template <class EncoderFixture>
399 class FromEncoderFixture {
400  public:
GetInitSlices()401   static std::vector<grpc_slice> GetInitSlices() { return Generate(0); }
GetBenchmarkSlices()402   static std::vector<grpc_slice> GetBenchmarkSlices() { return Generate(1); }
403 
404  private:
Generate(int iteration)405   static std::vector<grpc_slice> Generate(int iteration) {
406     grpc_core::ExecCtx exec_ctx;
407 
408     grpc_core::MemoryAllocator memory_allocator =
409         grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
410                                        ->memory_quota()
411                                        ->CreateMemoryAllocator("test"));
412     auto arena = grpc_core::MakeScopedArena(1024, &memory_allocator);
413     grpc_metadata_batch b;
414     EncoderFixture::Prepare(&b);
415 
416     grpc_core::HPackCompressor c;
417     grpc_transport_one_way_stats stats;
418     std::vector<grpc_slice> out;
419     stats = {};
420     bool done = false;
421     int i = 0;
422     while (!done) {
423       grpc_slice_buffer outbuf;
424       grpc_slice_buffer_init(&outbuf);
425       c.EncodeHeaders(
426           grpc_core::HPackCompressor::EncodeHeaderOptions{
427               static_cast<uint32_t>(i),
428               false,
429               EncoderFixture::kEnableTrueBinary,
430               1024 * 1024,
431               &stats,
432           },
433           b, &outbuf);
434       if (i == iteration) {
435         for (size_t s = 0; s < outbuf.count; s++) {
436           out.push_back(grpc_slice_ref(outbuf.slices[s]));
437         }
438         done = true;
439       }
440       grpc_slice_buffer_reset_and_unref(&outbuf);
441       grpc_core::ExecCtx::Get()->Flush();
442       grpc_slice_buffer_destroy(&outbuf);
443       i++;
444     }
445     // Remove the HTTP header.
446     GPR_ASSERT(!out.empty());
447     GPR_ASSERT(GRPC_SLICE_LENGTH(out[0]) > 9);
448     out[0] = grpc_slice_sub_no_ref(out[0], 9, GRPC_SLICE_LENGTH(out[0]));
449     return out;
450   }
451 };
452 
453 class EmptyBatch {
454  public:
GetInitSlices()455   static std::vector<grpc_slice> GetInitSlices() { return {}; }
GetBenchmarkSlices()456   static std::vector<grpc_slice> GetBenchmarkSlices() {
457     return {MakeSlice({})};
458   }
459 };
460 
461 class IndexedSingleStaticElem {
462  public:
GetInitSlices()463   static std::vector<grpc_slice> GetInitSlices() {
464     return {MakeSlice(
465         {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})};
466   }
GetBenchmarkSlices()467   static std::vector<grpc_slice> GetBenchmarkSlices() {
468     return {MakeSlice({0xbe})};
469   }
470 };
471 
472 class AddIndexedSingleStaticElem {
473  public:
GetInitSlices()474   static std::vector<grpc_slice> GetInitSlices() { return {}; }
GetBenchmarkSlices()475   static std::vector<grpc_slice> GetBenchmarkSlices() {
476     return {MakeSlice(
477         {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})};
478   }
479 };
480 
481 class KeyIndexedSingleStaticElem {
482  public:
GetInitSlices()483   static std::vector<grpc_slice> GetInitSlices() {
484     return {MakeSlice(
485         {0x40, 0x07, ':', 's', 't', 'a', 't', 'u', 's', 0x03, '2', '0', '0'})};
486   }
GetBenchmarkSlices()487   static std::vector<grpc_slice> GetBenchmarkSlices() {
488     return {MakeSlice({0x7e, 0x03, '4', '0', '4'})};
489   }
490 };
491 
492 class IndexedSingleInternedElem {
493  public:
GetInitSlices()494   static std::vector<grpc_slice> GetInitSlices() {
495     return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})};
496   }
GetBenchmarkSlices()497   static std::vector<grpc_slice> GetBenchmarkSlices() {
498     return {MakeSlice({0xbe})};
499   }
500 };
501 
502 class AddIndexedSingleInternedElem {
503  public:
GetInitSlices()504   static std::vector<grpc_slice> GetInitSlices() { return {}; }
GetBenchmarkSlices()505   static std::vector<grpc_slice> GetBenchmarkSlices() {
506     return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})};
507   }
508 };
509 
510 class KeyIndexedSingleInternedElem {
511  public:
GetInitSlices()512   static std::vector<grpc_slice> GetInitSlices() {
513     return {MakeSlice({0x40, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})};
514   }
GetBenchmarkSlices()515   static std::vector<grpc_slice> GetBenchmarkSlices() {
516     return {MakeSlice({0x7e, 0x03, 'g', 'h', 'i'})};
517   }
518 };
519 
520 class NonIndexedElem {
521  public:
GetInitSlices()522   static std::vector<grpc_slice> GetInitSlices() { return {}; }
GetBenchmarkSlices()523   static std::vector<grpc_slice> GetBenchmarkSlices() {
524     return {MakeSlice({0x00, 0x03, 'a', 'b', 'c', 0x03, 'd', 'e', 'f'})};
525   }
526 };
527 
528 template <int kLength, bool kTrueBinary>
529 class NonIndexedBinaryElem;
530 
531 template <int kLength>
532 class NonIndexedBinaryElem<kLength, true> {
533  public:
GetInitSlices()534   static std::vector<grpc_slice> GetInitSlices() { return {}; }
GetBenchmarkSlices()535   static std::vector<grpc_slice> GetBenchmarkSlices() {
536     std::vector<uint8_t> v = {
537         0x00, 0x07, 'a', 'b', 'c',
538         '-',  'b',  'i', 'n', static_cast<uint8_t>(kLength + 1),
539         0};
540     for (int i = 0; i < kLength; i++) {
541       v.push_back(static_cast<uint8_t>(i));
542     }
543     return {MakeSlice(v)};
544   }
545 };
546 
547 template <>
548 class NonIndexedBinaryElem<1, false> {
549  public:
GetInitSlices()550   static std::vector<grpc_slice> GetInitSlices() { return {}; }
GetBenchmarkSlices()551   static std::vector<grpc_slice> GetBenchmarkSlices() {
552     return {MakeSlice(
553         {0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x82, 0xf7, 0xb3})};
554   }
555 };
556 
557 template <>
558 class NonIndexedBinaryElem<3, false> {
559  public:
GetInitSlices()560   static std::vector<grpc_slice> GetInitSlices() { return {}; }
GetBenchmarkSlices()561   static std::vector<grpc_slice> GetBenchmarkSlices() {
562     return {MakeSlice({0x00, 0x07, 'a', 'b', 'c', '-', 'b', 'i', 'n', 0x84,
563                        0x7f, 0x4e, 0x29, 0x3f})};
564   }
565 };
566 
567 template <>
568 class NonIndexedBinaryElem<10, false> {
569  public:
GetInitSlices()570   static std::vector<grpc_slice> GetInitSlices() { return {}; }
GetBenchmarkSlices()571   static std::vector<grpc_slice> GetBenchmarkSlices() {
572     return {MakeSlice({0x00, 0x07, 'a',  'b',  'c',  '-',  'b',
573                        'i',  'n',  0x8b, 0x71, 0x0c, 0xa5, 0x81,
574                        0x73, 0x7b, 0x47, 0x13, 0xe9, 0xf7, 0xe3})};
575   }
576 };
577 
578 template <>
579 class NonIndexedBinaryElem<31, false> {
580  public:
GetInitSlices()581   static std::vector<grpc_slice> GetInitSlices() { return {}; }
GetBenchmarkSlices()582   static std::vector<grpc_slice> GetBenchmarkSlices() {
583     return {MakeSlice({0x00, 0x07, 'a',  'b',  'c',  '-',  'b',  'i',  'n',
584                        0xa3, 0x92, 0x43, 0x7f, 0xbe, 0x7c, 0xea, 0x6f, 0xf3,
585                        0x3d, 0xa7, 0xa7, 0x67, 0xfb, 0xe2, 0x82, 0xf7, 0xf2,
586                        0x8f, 0x1f, 0x9d, 0xdf, 0xf1, 0x7e, 0xb3, 0xef, 0xb2,
587                        0x8f, 0x53, 0x77, 0xce, 0x0c, 0x13, 0xe3, 0xfd, 0x87})};
588   }
589 };
590 
591 template <>
592 class NonIndexedBinaryElem<100, false> {
593  public:
GetInitSlices()594   static std::vector<grpc_slice> GetInitSlices() { return {}; }
GetBenchmarkSlices()595   static std::vector<grpc_slice> GetBenchmarkSlices() {
596     return {MakeSlice(
597         {0x00, 0x07, 'a',  'b',  'c',  '-',  'b',  'i',  'n',  0xeb, 0x1d, 0x4d,
598          0xe8, 0x96, 0x8c, 0x14, 0x20, 0x06, 0xc1, 0xc3, 0xdf, 0x6e, 0x1f, 0xef,
599          0xde, 0x2f, 0xde, 0xb7, 0xf2, 0xfe, 0x6d, 0xd4, 0xe4, 0x7d, 0xf5, 0x55,
600          0x46, 0x52, 0x3d, 0x91, 0xf2, 0xd4, 0x6f, 0xca, 0x34, 0xcd, 0xd9, 0x39,
601          0xbd, 0x03, 0x27, 0xe3, 0x9c, 0x74, 0xcc, 0x17, 0x34, 0xed, 0xa6, 0x6a,
602          0x77, 0x73, 0x10, 0xcd, 0x8e, 0x4e, 0x5c, 0x7c, 0x72, 0x39, 0xd8, 0xe6,
603          0x78, 0x6b, 0xdb, 0xa5, 0xb7, 0xab, 0xe7, 0x46, 0xae, 0x21, 0xab, 0x7f,
604          0x01, 0x89, 0x13, 0xd7, 0xca, 0x17, 0x6e, 0xcb, 0xd6, 0x79, 0x71, 0x68,
605          0xbf, 0x8a, 0x3f, 0x32, 0xe8, 0xba, 0xf5, 0xbe, 0xb3, 0xbc, 0xde, 0x28,
606          0xc7, 0xcf, 0x62, 0x7a, 0x58, 0x2c, 0xcf, 0x4d, 0xe3})};
607   }
608 };
609 
610 using RepresentativeClientInitialMetadata = FromEncoderFixture<
611     hpack_encoder_fixtures::RepresentativeClientInitialMetadata>;
612 using RepresentativeServerInitialMetadata = FromEncoderFixture<
613     hpack_encoder_fixtures::RepresentativeServerInitialMetadata>;
614 using RepresentativeServerTrailingMetadata = FromEncoderFixture<
615     hpack_encoder_fixtures::RepresentativeServerTrailingMetadata>;
616 using MoreRepresentativeClientInitialMetadata = FromEncoderFixture<
617     hpack_encoder_fixtures::MoreRepresentativeClientInitialMetadata>;
618 
619 // Send the same deadline repeatedly
620 class SameDeadline {
621  public:
GetInitSlices()622   static std::vector<grpc_slice> GetInitSlices() {
623     return {
624         grpc_slice_from_static_string("@\x0cgrpc-timeout\x03"
625                                       "30S")};
626   }
GetBenchmarkSlices()627   static std::vector<grpc_slice> GetBenchmarkSlices() {
628     // Use saved key and literal value.
629     return {MakeSlice({0x0f, 0x2f, 0x03, '3', '0', 'S'})};
630   }
631 };
632 
633 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, EmptyBatch);
634 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleStaticElem);
635 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleStaticElem);
636 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleStaticElem);
637 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, IndexedSingleInternedElem);
638 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, AddIndexedSingleInternedElem);
639 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, KeyIndexedSingleInternedElem);
640 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedElem);
641 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, false>);
642 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, false>);
643 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, false>);
644 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, false>);
645 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, false>);
646 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<1, true>);
647 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<3, true>);
648 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<10, true>);
649 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<31, true>);
650 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, NonIndexedBinaryElem<100, true>);
651 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
652                    RepresentativeClientInitialMetadata);
653 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
654                    MoreRepresentativeClientInitialMetadata);
655 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
656                    RepresentativeServerInitialMetadata);
657 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
658                    RepresentativeServerTrailingMetadata);
659 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
660                    RepresentativeClientInitialMetadata);
661 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
662                    MoreRepresentativeClientInitialMetadata);
663 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader,
664                    RepresentativeServerInitialMetadata);
665 BENCHMARK_TEMPLATE(BM_HpackParserParseHeader, SameDeadline);
666 
667 }  // namespace hpack_parser_fixtures
668 
669 // Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
670 // and others do not. This allows us to support both modes.
671 namespace benchmark {
RunTheBenchmarksNamespaced()672 void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
673 }  // namespace benchmark
674 
main(int argc,char ** argv)675 int main(int argc, char** argv) {
676   grpc::testing::TestEnvironment env(&argc, argv);
677   LibraryInitializer libInit;
678   ::benchmark::Initialize(&argc, argv);
679   grpc::testing::InitTest(&argc, &argv, false);
680   benchmark::RunTheBenchmarksNamespaced();
681   return 0;
682 }
683