// Protocol Buffers - Google's data interchange format // Copyright 2025 Google LLC. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd #include #include #include #include #include #include #include "absl/container/flat_hash_set.h" #include "upb/mem/alloc.h" #include "upb/mem/arena.h" #include "upb/message/message.h" #include "upb/mini_table/message.h" #include "upb/wire/decode.h" #include "upb/wire/decode_fast/combinations.h" #include "upb/wire/test_util/field_types.h" #include "upb/wire/test_util/make_mini_table.h" #include "upb/wire/test_util/wire_message.h" // Must be last. #include "upb/port/def.inc" namespace upb { namespace test { namespace { void BM_Decode(benchmark::State& state, const upb_MiniTable* mt, std::string payload, bool alias, bool initial_block) { char mem[4096]; int decode_options = 0; for (auto s : state) { upb_Arena* arena = initial_block ? upb_Arena_Init(mem, 4096, &upb_alloc_global) : upb_Arena_New(); upb_Message* msg = upb_Message_New(mt, arena); upb_DecodeStatus result = upb_Decode(payload.data(), payload.size(), msg, mt, nullptr, decode_options, arena); ASSERT_EQ(result, kUpb_DecodeStatus_Ok) << upb_DecodeStatus_String(result); upb_Arena_Free(arena); } state.SetBytesProcessed(state.iterations() * payload.size()); } [[maybe_unused]] upb_Arena* benchmark_registration = [] { upb_Arena* arena = upb_Arena_New(); std::vector sizes{8, 64, 512}; for (size_t size : sizes) { absl::flat_hash_set fast_types; ForEachType([&](auto&& type) { using Type = std::remove_reference_t; // We only need to benchmark each wire type once, since they are all // treated the same by the decoder. if (!fast_types.insert(Type::kFastType).second) return; std::vector initial_block{true, false}; for (bool init : initial_block) { auto [mt, field] = MiniTable::MakeSingleFieldTable( 1, kUpb_DecodeFast_Scalar, arena); std::string payload; while (payload.size() < size) { payload.append(ToBinaryPayload(wire_types::WireMessage{ {1, Type::WireValue(typename Type::Value{})}})); } ::benchmark::RegisterBenchmark( absl::StrFormat("BM_Decode/%s/%zu/%s", Type::kName, size, init ? "InitialBlock" : "NoInitialBlock") .c_str(), BM_Decode, mt, payload, false, init); } }); } return arena; }(); } // namespace } // namespace test } // namespace upb