bm_chttp2_hpack.cc 24 KB

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